· 7 years ago · Feb 19, 2019, 02:06 PM
1<%--
2 jsp File browser 1.1a
3 Copyright (C) 2003,2004, Boris von Loesch
4 This program is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2 of the License, or (at your option)
7 any later version.
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11 You should have received a copy of the GNU General Public License along with
12 this program; if not, write to the
13 Free Software Foundation, Inc.,
14 59 Temple Place, Suite 330,
15 Boston, MA 02111-1307 USA
16 - Description: jsp File browser v1.1a -- This JSP program allows remote web-based
17 file access and manipulation. You can copy, create, move and delete files.
18 Text files can be edited and groups of files and folders can be downloaded
19 as a single zip file that's created on the fly.
20 - Credits: Taylor Bastien, David Levine, David Cowan, Lieven Govaerts
21--%>
22<%@page import="java.util.*,
23 java.net.*,
24 java.text.*,
25 java.util.zip.*,
26 java.io.*"
27%>
28<%!
29 //FEATURES
30 private static final boolean NATIVE_COMMANDS = true;
31
32 //Allow browsing and file manipulation only in certain directories
33 private static final boolean RESTRICT_BROWSING = false;
34 //If true, the user is allowed to browse only in RESTRICT_PATH,
35 //if false, the user is allowed to browse all directories besides RESTRICT_PATH
36 private static final boolean RESTRICT_WHITELIST = false;
37 //Paths, sperated by semicolon
38 //private static final String RESTRICT_PATH = "C:\\CODE;E:\\"; //Win32: Case important!!
39 private static final String RESTRICT_PATH = "/etc;/var";
40
41 //The refresh time in seconds of the upload monitor window
42 private static final int UPLOAD_MONITOR_REFRESH = 2;
43 //The number of colums for the edit field
44 private static final int EDITFIELD_COLS = 85;
45 //The number of rows for the edit field
46 private static final int EDITFIELD_ROWS = 30;
47 //Open a new window to view a file
48 private static final boolean USE_POPUP = true;
49 /**
50 * If USE_DIR_PREVIEW = true, then for every directory a tooltip will be
51 * created (hold the mouse over the link) with the first DIR_PREVIEW_NUMBER entries.
52 * This can yield to performance issues. Turn it of, if the directory loads to slow.
53 */
54 private static final boolean USE_DIR_PREVIEW = true;
55 private static final int DIR_PREVIEW_NUMBER = 10;
56 /**
57 * The name of an optional CSS Stylesheet file
58 */
59 /**
60 * The compression level for zip file creation (0-9)
61 * 0 = No compression
62 * 1 = Standard compression (Very fast)
63 * ...
64 * 9 = Best compression (Very slow)
65 */
66 private static final int COMPRESSION_LEVEL = 1;
67 /**
68 * The FORBIDDEN_DRIVES are not displayed on the list. This can be usefull, if the
69 * server runs on a windows platform, to avoid a message box, if you try to access
70 * an empty removable drive (See KNOWN BUGS in Readme.txt).
71 */
72 private static final String[] FORBIDDEN_DRIVES = {"a:\\"};
73
74 /**
75 * Command of the shell interpreter and the parameter to run a programm
76 */
77 private static final String[] COMMAND_INTERPRETER = {"cmd", "/C"}; // Dos,Windows
78 //private static final String[] COMMAND_INTERPRETER = {"/bin/sh","-c"}; // Unix
79
80 /**
81 * Max time in ms a process is allowed to run, before it will be terminated
82 */
83 private static final long MAX_PROCESS_RUNNING_TIME = 30 * 1000; //30 seconds
84
85 //Button names
86 private static final String SAVE_AS_ZIP = "Download selected files as zip";
87 private static final String RENAME_FILE = "Rename File";
88 private static final String DELETE_FILES = "Delete selected files";
89 private static final String CREATE_DIR = "Create Dir";
90 private static final String CREATE_FILE = "Create File";
91 private static final String MOVE_FILES = "Move Files";
92 private static final String COPY_FILES = "Copy Files";
93
94 //Normally you should not change anything after this line
95 //----------------------------------------------------------------------------------
96 //Change this to locate the tempfile directory for upload (not longer needed)
97 private static String tempdir = ".";
98 private static String VERSION_NR = "1.1a";
99 private static DateFormat dateFormat = DateFormat.getDateTimeInstance();
100
101 public class UplInfo {
102
103 public long totalSize;
104 public long currSize;
105 public long starttime;
106 public boolean aborted;
107
108 public UplInfo() {
109 totalSize = 0l;
110 currSize = 0l;
111 starttime = System.currentTimeMillis();
112 aborted = false;
113 }
114
115 public UplInfo(int size) {
116 totalSize = size;
117 currSize = 0;
118 starttime = System.currentTimeMillis();
119 aborted = false;
120 }
121
122 public String getUprate() {
123 long time = System.currentTimeMillis() - starttime;
124 if (time != 0) {
125 long uprate = currSize * 1000 / time;
126 return convertFileSize(uprate) + "/s";
127 }
128 else return "n/a";
129 }
130
131 public int getPercent() {
132 if (totalSize == 0) return 0;
133 else return (int) (currSize * 100 / totalSize);
134 }
135
136 public String getTimeElapsed() {
137 long time = (System.currentTimeMillis() - starttime) / 1000l;
138 if (time - 60l >= 0){
139 if (time % 60 >=10) return time / 60 + ":" + (time % 60) + "m";
140 else return time / 60 + ":0" + (time % 60) + "m";
141 }
142 else return time<10 ? "0" + time + "s": time + "s";
143 }
144
145 public String getTimeEstimated() {
146 if (currSize == 0) return "n/a";
147 long time = System.currentTimeMillis() - starttime;
148 time = totalSize * time / currSize;
149 time /= 1000l;
150 if (time - 60l >= 0){
151 if (time % 60 >=10) return time / 60 + ":" + (time % 60) + "m";
152 else return time / 60 + ":0" + (time % 60) + "m";
153 }
154 else return time<10 ? "0" + time + "s": time + "s";
155 }
156
157 }
158
159 public class FileInfo {
160
161 public String name = null, clientFileName = null, fileContentType = null;
162 private byte[] fileContents = null;
163 public File file = null;
164 public StringBuffer sb = new StringBuffer(100);
165
166 public void setFileContents(byte[] aByteArray) {
167 fileContents = new byte[aByteArray.length];
168 System.arraycopy(aByteArray, 0, fileContents, 0, aByteArray.length);
169 }
170 }
171
172 public static class UploadMonitor {
173
174 static Hashtable uploadTable = new Hashtable();
175
176 static void set(String fName, UplInfo info) {
177 uploadTable.put(fName, info);
178 }
179
180 static void remove(String fName) {
181 uploadTable.remove(fName);
182 }
183
184 static UplInfo getInfo(String fName) {
185 UplInfo info = (UplInfo) uploadTable.get(fName);
186 return info;
187 }
188 }
189
190 // A Class with methods used to process a ServletInputStream
191 public class HttpMultiPartParser {
192
193 private final String lineSeparator = System.getProperty("line.separator", "\n");
194 private final int ONE_MB = 1024 * 1;
195
196 public Hashtable processData(ServletInputStream is, String boundary, String saveInDir,
197 int clength) throws IllegalArgumentException, IOException {
198 if (is == null) throw new IllegalArgumentException("InputStream");
199 if (boundary == null || boundary.trim().length() < 1) throw new IllegalArgumentException(
200 "\"" + boundary + "\" is an illegal boundary indicator");
201 boundary = "--" + boundary;
202 StringTokenizer stLine = null, stFields = null;
203 FileInfo fileInfo = null;
204 Hashtable dataTable = new Hashtable(5);
205 String line = null, field = null, paramName = null;
206 boolean saveFiles = (saveInDir != null && saveInDir.trim().length() > 0);
207 boolean isFile = false;
208 if (saveFiles) { // Create the required directory (including parent dirs)
209 File f = new File(saveInDir);
210 f.mkdirs();
211 }
212 line = getLine(is);
213 if (line == null || !line.startsWith(boundary)) throw new IOException(
214 "Boundary not found; boundary = " + boundary + ", line = " + line);
215 while (line != null) {
216 if (line == null || !line.startsWith(boundary)) return dataTable;
217 line = getLine(is);
218 if (line == null) return dataTable;
219 stLine = new StringTokenizer(line, ";\r\n");
220 if (stLine.countTokens() < 2) throw new IllegalArgumentException(
221 "Bad data in second line");
222 line = stLine.nextToken().toLowerCase();
223 if (line.indexOf("form-data") < 0) throw new IllegalArgumentException(
224 "Bad data in second line");
225 stFields = new StringTokenizer(stLine.nextToken(), "=\"");
226 if (stFields.countTokens() < 2) throw new IllegalArgumentException(
227 "Bad data in second line");
228 fileInfo = new FileInfo();
229 stFields.nextToken();
230 paramName = stFields.nextToken();
231 isFile = false;
232 if (stLine.hasMoreTokens()) {
233 field = stLine.nextToken();
234 stFields = new StringTokenizer(field, "=\"");
235 if (stFields.countTokens() > 1) {
236 if (stFields.nextToken().trim().equalsIgnoreCase("filename")) {
237 fileInfo.name = paramName;
238 String value = stFields.nextToken();
239 if (value != null && value.trim().length() > 0) {
240 fileInfo.clientFileName = value;
241 isFile = true;
242 }
243 else {
244 line = getLine(is); // Skip "Content-Type:" line
245 line = getLine(is); // Skip blank line
246 line = getLine(is); // Skip blank line
247 line = getLine(is); // Position to boundary line
248 continue;
249 }
250 }
251 }
252 else if (field.toLowerCase().indexOf("filename") >= 0) {
253 line = getLine(is); // Skip "Content-Type:" line
254 line = getLine(is); // Skip blank line
255 line = getLine(is); // Skip blank line
256 line = getLine(is); // Position to boundary line
257 continue;
258 }
259 }
260 boolean skipBlankLine = true;
261 if (isFile) {
262 line = getLine(is);
263 if (line == null) return dataTable;
264 if (line.trim().length() < 1) skipBlankLine = false;
265 else {
266 stLine = new StringTokenizer(line, ": ");
267 if (stLine.countTokens() < 2) throw new IllegalArgumentException(
268 "Bad data in third line");
269 stLine.nextToken(); // Content-Type
270 fileInfo.fileContentType = stLine.nextToken();
271 }
272 }
273 if (skipBlankLine) {
274 line = getLine(is);
275 if (line == null) return dataTable;
276 }
277 if (!isFile) {
278 line = getLine(is);
279 if (line == null) return dataTable;
280 dataTable.put(paramName, line);
281 // If parameter is dir, change saveInDir to dir
282 if (paramName.equals("dir")) saveInDir = line;
283 line = getLine(is);
284 continue;
285 }
286 try {
287 UplInfo uplInfo = new UplInfo(clength);
288 UploadMonitor.set(fileInfo.clientFileName, uplInfo);
289 OutputStream os = null;
290 String path = null;
291 if (saveFiles) os = new FileOutputStream(path = getFileName(saveInDir,
292 fileInfo.clientFileName));
293 else os = new ByteArrayOutputStream(ONE_MB);
294 boolean readingContent = true;
295 byte previousLine[] = new byte[2 * ONE_MB];
296 byte temp[] = null;
297 byte currentLine[] = new byte[2 * ONE_MB];
298 int read, read3;
299 if ((read = is.readLine(previousLine, 0, previousLine.length)) == -1) {
300 line = null;
301 break;
302 }
303 while (readingContent) {
304 if ((read3 = is.readLine(currentLine, 0, currentLine.length)) == -1) {
305 line = null;
306 uplInfo.aborted = true;
307 break;
308 }
309 if (compareBoundary(boundary, currentLine)) {
310 os.write(previousLine, 0, read - 2);
311 line = new String(currentLine, 0, read3);
312 break;
313 }
314 else {
315 os.write(previousLine, 0, read);
316 uplInfo.currSize += read;
317 temp = currentLine;
318 currentLine = previousLine;
319 previousLine = temp;
320 read = read3;
321 }//end else
322 }//end while
323 os.flush();
324 os.close();
325 if (!saveFiles) {
326 ByteArrayOutputStream baos = (ByteArrayOutputStream) os;
327 fileInfo.setFileContents(baos.toByteArray());
328 }
329 else fileInfo.file = new File(path);
330 dataTable.put(paramName, fileInfo);
331 uplInfo.currSize = uplInfo.totalSize;
332 }//end try
333 catch (IOException e) {
334 throw e;
335 }
336 }
337 return dataTable;
338 }
339
340 /**
341 * Compares boundary string to byte array
342 */
343 private boolean compareBoundary(String boundary, byte ba[]) {
344 byte b;
345 if (boundary == null || ba == null) return false;
346 for (int i = 0; i < boundary.length(); i++)
347 if ((byte) boundary.charAt(i) != ba[i]) return false;
348 return true;
349 }
350
351 /** Convenience method to read HTTP header lines */
352 private synchronized String getLine(ServletInputStream sis) throws IOException {
353 byte b[] = new byte[1024];
354 int read = sis.readLine(b, 0, b.length), index;
355 String line = null;
356 if (read != -1) {
357 line = new String(b, 0, read);
358 if ((index = line.indexOf('\n')) >= 0) line = line.substring(0, index - 1);
359 }
360 return line;
361 }
362
363 public String getFileName(String dir, String fileName) throws IllegalArgumentException {
364 String path = null;
365 if (dir == null || fileName == null) throw new IllegalArgumentException(
366 "dir or fileName is null");
367 int index = fileName.lastIndexOf('/');
368 String name = null;
369 if (index >= 0) name = fileName.substring(index + 1);
370 else name = fileName;
371 index = name.lastIndexOf('\\');
372 if (index >= 0) fileName = name.substring(index + 1);
373 path = dir + File.separator + fileName;
374 if (File.separatorChar == '/') return path.replace('\\', File.separatorChar);
375 else return path.replace('/', File.separatorChar);
376 }
377 } //End of class HttpMultiPartParser
378
379 /**
380 * This class is a comparator to sort the filenames and dirs
381 */
382 class FileComp implements Comparator {
383
384 int mode;
385 int sign;
386
387 FileComp() {
388 this.mode = 1;
389 this.sign = 1;
390 }
391
392 /**
393 * @param mode sort by 1=Filename, 2=Size, 3=Date, 4=Type
394 * The default sorting method is by Name
395 * Negative mode means descending sort
396 */
397 FileComp(int mode) {
398 if (mode < 0) {
399 this.mode = -mode;
400 sign = -1;
401 }
402 else {
403 this.mode = mode;
404 this.sign = 1;
405 }
406 }
407
408 public int compare(Object o1, Object o2) {
409 File f1 = (File) o1;
410 File f2 = (File) o2;
411 if (f1.isDirectory()) {
412 if (f2.isDirectory()) {
413 switch (mode) {
414 //Filename or Type
415 case 1:
416 case 4:
417 return sign
418 * f1.getAbsolutePath().toUpperCase().compareTo(
419 f2.getAbsolutePath().toUpperCase());
420 //Filesize
421 case 2:
422 return sign * (new Long(f1.length()).compareTo(new Long(f2.length())));
423 //Date
424 case 3:
425 return sign
426 * (new Long(f1.lastModified())
427 .compareTo(new Long(f2.lastModified())));
428 default:
429 return 1;
430 }
431 }
432 else return -1;
433 }
434 else if (f2.isDirectory()) return 1;
435 else {
436 switch (mode) {
437 case 1:
438 return sign
439 * f1.getAbsolutePath().toUpperCase().compareTo(
440 f2.getAbsolutePath().toUpperCase());
441 case 2:
442 return sign * (new Long(f1.length()).compareTo(new Long(f2.length())));
443 case 3:
444 return sign
445 * (new Long(f1.lastModified()).compareTo(new Long(f2.lastModified())));
446 case 4: { // Sort by extension
447 int tempIndexf1 = f1.getAbsolutePath().lastIndexOf('.');
448 int tempIndexf2 = f2.getAbsolutePath().lastIndexOf('.');
449 if ((tempIndexf1 == -1) && (tempIndexf2 == -1)) { // Neither have an extension
450 return sign
451 * f1.getAbsolutePath().toUpperCase().compareTo(
452 f2.getAbsolutePath().toUpperCase());
453 }
454 // f1 has no extension
455 else if (tempIndexf1 == -1) return -sign;
456 // f2 has no extension
457 else if (tempIndexf2 == -1) return sign;
458 // Both have an extension
459 else {
460 String tempEndf1 = f1.getAbsolutePath().toUpperCase()
461 .substring(tempIndexf1);
462 String tempEndf2 = f2.getAbsolutePath().toUpperCase()
463 .substring(tempIndexf2);
464 return sign * tempEndf1.compareTo(tempEndf2);
465 }
466 }
467 default:
468 return 1;
469 }
470 }
471 }
472 }
473
474 /**
475 * Wrapperclass to wrap an OutputStream around a Writer
476 */
477 class Writer2Stream extends OutputStream {
478
479 Writer out;
480
481 Writer2Stream(Writer w) {
482 super();
483 out = w;
484 }
485
486 public void write(int i) throws IOException {
487 out.write(i);
488 }
489
490 public void write(byte[] b) throws IOException {
491 for (int i = 0; i < b.length; i++) {
492 int n = b[i];
493 //Convert byte to ubyte
494 n = ((n >>> 4) & 0xF) * 16 + (n & 0xF);
495 out.write(n);
496 }
497 }
498
499 public void write(byte[] b, int off, int len) throws IOException {
500 for (int i = off; i < off + len; i++) {
501 int n = b[i];
502 n = ((n >>> 4) & 0xF) * 16 + (n & 0xF);
503 out.write(n);
504 }
505 }
506 } //End of class Writer2Stream
507
508 static Vector expandFileList(String[] files, boolean inclDirs) {
509 Vector v = new Vector();
510 if (files == null) return v;
511 for (int i = 0; i < files.length; i++)
512 v.add(new File(URLDecoder.decode(files[i])));
513 for (int i = 0; i < v.size(); i++) {
514 File f = (File) v.get(i);
515 if (f.isDirectory()) {
516 File[] fs = f.listFiles();
517 for (int n = 0; n < fs.length; n++)
518 v.add(fs[n]);
519 if (!inclDirs) {
520 v.remove(i);
521 i--;
522 }
523 }
524 }
525 return v;
526 }
527
528 /**
529 * Method to build an absolute path
530 * @param dir the root dir
531 * @param name the name of the new directory
532 * @return if name is an absolute directory, returns name, else returns dir+name
533 */
534 static String getDir(String dir, String name) {
535 if (!dir.endsWith(File.separator)) dir = dir + File.separator;
536 File mv = new File(name);
537 String new_dir = null;
538 if (!mv.isAbsolute()) {
539 new_dir = dir + name;
540 }
541 else new_dir = name;
542 return new_dir;
543 }
544
545 /**
546 * This Method converts a byte size in a kbytes or Mbytes size, depending on the size
547 * @param size The size in bytes
548 * @return String with size and unit
549 */
550 static String convertFileSize(long size) {
551 int divisor = 1;
552 String unit = "bytes";
553 if (size >= 1024 * 1024) {
554 divisor = 1024 * 1024;
555 unit = "MB";
556 }
557 else if (size >= 1024) {
558 divisor = 1024;
559 unit = "KB";
560 }
561 if (divisor == 1) return size / divisor + " " + unit;
562 String aftercomma = "" + 100 * (size % divisor) / divisor;
563 if (aftercomma.length() == 1) aftercomma = "0" + aftercomma;
564 return size / divisor + "." + aftercomma + " " + unit;
565 }
566
567 /**
568 * Copies all data from in to out
569 * @param in the input stream
570 * @param out the output stream
571 * @param buffer copy buffer
572 */
573 static void copyStreams(InputStream in, OutputStream out, byte[] buffer) throws IOException {
574 copyStreamsWithoutClose(in, out, buffer);
575 in.close();
576 out.close();
577 }
578
579 /**
580 * Copies all data from in to out
581 * @param in the input stream
582 * @param out the output stream
583 * @param buffer copy buffer
584 */
585 static void copyStreamsWithoutClose(InputStream in, OutputStream out, byte[] buffer)
586 throws IOException {
587 int b;
588 while ((b = in.read(buffer)) != -1)
589 out.write(buffer, 0, b);
590 }
591
592 /**
593 * Returns the Mime Type of the file, depending on the extension of the filename
594 */
595 static String getMimeType(String fName) {
596 fName = fName.toLowerCase();
597 if (fName.endsWith(".jpg") || fName.endsWith(".jpeg") || fName.endsWith(".jpe")) return "image/jpeg";
598 else if (fName.endsWith(".gif")) return "image/gif";
599 else if (fName.endsWith(".pdf")) return "application/pdf";
600 else if (fName.endsWith(".htm") || fName.endsWith(".html") || fName.endsWith(".shtml")) return "text/html";
601 else if (fName.endsWith(".avi")) return "video/x-msvideo";
602 else if (fName.endsWith(".mov") || fName.endsWith(".qt")) return "video/quicktime";
603 else if (fName.endsWith(".mpg") || fName.endsWith(".mpeg") || fName.endsWith(".mpe")) return "video/mpeg";
604 else if (fName.endsWith(".zip")) return "application/zip";
605 else if (fName.endsWith(".tiff") || fName.endsWith(".tif")) return "image/tiff";
606 else if (fName.endsWith(".rtf")) return "application/rtf";
607 else if (fName.endsWith(".mid") || fName.endsWith(".midi")) return "audio/x-midi";
608 else if (fName.endsWith(".xl") || fName.endsWith(".xls") || fName.endsWith(".xlv")
609 || fName.endsWith(".xla") || fName.endsWith(".xlb") || fName.endsWith(".xlt")
610 || fName.endsWith(".xlm") || fName.endsWith(".xlk")) return "application/excel";
611 else if (fName.endsWith(".doc") || fName.endsWith(".dot")) return "application/msword";
612 else if (fName.endsWith(".png")) return "image/png";
613 else if (fName.endsWith(".xml")) return "text/xml";
614 else if (fName.endsWith(".svg")) return "image/svg+xml";
615 else if (fName.endsWith(".mp3")) return "audio/mp3";
616 else if (fName.endsWith(".ogg")) return "audio/ogg";
617 else return "text/plain";
618 }
619
620 /**
621 * Converts some important chars (int) to the corresponding html string
622 */
623 static String conv2Html(int i) {
624 if (i == '&') return "&";
625 else if (i == '<') return "<";
626 else if (i == '>') return ">";
627 else if (i == '"') return """;
628 else return "" + (char) i;
629 }
630
631 /**
632 * Converts a normal string to a html conform string
633 */
634 static String conv2Html(String st) {
635 StringBuffer buf = new StringBuffer();
636 for (int i = 0; i < st.length(); i++) {
637 buf.append(conv2Html(st.charAt(i)));
638 }
639 return buf.toString();
640 }
641
642 /**
643 * Starts a native process on the server
644 * @param command the command to start the process
645 * @param dir the dir in which the process starts
646 */
647 static String startProcess(String command, String dir) throws IOException {
648 StringBuffer ret = new StringBuffer();
649 String[] comm = new String[3];
650 comm[0] = COMMAND_INTERPRETER[0];
651 comm[1] = COMMAND_INTERPRETER[1];
652 comm[2] = command;
653 long start = System.currentTimeMillis();
654 try {
655 //Start process
656 Process ls_proc = Runtime.getRuntime().exec(comm, null, new File(dir));
657 //Get input and error streams
658 BufferedInputStream ls_in = new BufferedInputStream(ls_proc.getInputStream());
659 BufferedInputStream ls_err = new BufferedInputStream(ls_proc.getErrorStream());
660 boolean end = false;
661 while (!end) {
662 int c = 0;
663 while ((ls_err.available() > 0) && (++c <= 1000)) {
664 ret.append(conv2Html(ls_err.read()));
665 }
666 c = 0;
667 while ((ls_in.available() > 0) && (++c <= 1000)) {
668 ret.append(conv2Html(ls_in.read()));
669 }
670 try {
671 ls_proc.exitValue();
672 //if the process has not finished, an exception is thrown
673 //else
674 while (ls_err.available() > 0)
675 ret.append(conv2Html(ls_err.read()));
676 while (ls_in.available() > 0)
677 ret.append(conv2Html(ls_in.read()));
678 end = true;
679 }
680 catch (IllegalThreadStateException ex) {
681 //Process is running
682 }
683 //The process is not allowed to run longer than given time.
684 if (System.currentTimeMillis() - start > MAX_PROCESS_RUNNING_TIME) {
685 ls_proc.destroy();
686 end = true;
687 ret.append("!!!! Process has timed out, destroyed !!!!!");
688 }
689 try {
690 Thread.sleep(50);
691 }
692 catch (InterruptedException ie) {}
693 }
694 }
695 catch (IOException e) {
696 ret.append("Error: " + e);
697 }
698 return ret.toString();
699 }
700
701 /**
702 * Converts a dir string to a linked dir string
703 * @param dir the directory string (e.g. /usr/local/httpd)
704 * @param browserLink web-path to Browser.jsp
705 */
706 static String dir2linkdir(String dir, String browserLink, int sortMode) {
707 File f = new File(dir);
708 StringBuffer buf = new StringBuffer();
709 while (f.getParentFile() != null) {
710 if (f.canRead()) {
711 String encPath = URLEncoder.encode(f.getAbsolutePath());
712 buf.insert(0, "<a href=\"" + browserLink + "?sort=" + sortMode + "&dir="
713 + encPath + "\">" + conv2Html(f.getName()) + File.separator + "</a>");
714 }
715 else buf.insert(0, conv2Html(f.getName()) + File.separator);
716 f = f.getParentFile();
717 }
718 if (f.canRead()) {
719 String encPath = URLEncoder.encode(f.getAbsolutePath());
720 buf.insert(0, "<a href=\"" + browserLink + "?sort=" + sortMode + "&dir=" + encPath
721 + "\">" + conv2Html(f.getAbsolutePath()) + "</a>");
722 }
723 else buf.insert(0, f.getAbsolutePath());
724 return buf.toString();
725 }
726
727 /**
728 * Returns true if the given filename tends towards a packed file
729 */
730 static boolean isPacked(String name, boolean gz) {
731 return (name.toLowerCase().endsWith(".zip") || name.toLowerCase().endsWith(".jar")
732 || (gz && name.toLowerCase().endsWith(".gz")) || name.toLowerCase()
733 .endsWith(".war"));
734 }
735
736 /**
737 * If RESTRICT_BROWSING = true this method checks, whether the path is allowed or not
738 */
739 static boolean isAllowed(File path) throws IOException{
740 if (RESTRICT_BROWSING) {
741 StringTokenizer stk = new StringTokenizer(RESTRICT_PATH, ";");
742 while (stk.hasMoreTokens()){
743 if (path!=null && path.getCanonicalPath().startsWith(stk.nextToken()))
744 return RESTRICT_WHITELIST;
745 }
746 return !RESTRICT_WHITELIST;
747 }
748 else return true;
749 }
750
751 //---------------------------------------------------------------------------------------------------------------
752
753 %>
754<%
755 //Get the current browsing directory
756 request.setAttribute("dir", request.getParameter("dir"));
757 // The browser_name variable is used to keep track of the URI
758 // of the jsp file itself. It is used in all link-backs.
759 final String browser_name = request.getRequestURI();
760 final String FOL_IMG = "";
761 boolean nohtml = false;
762 boolean dir_view = true;
763 // View file
764 if (request.getParameter("file") != null) {
765 File f = new File(request.getParameter("file"));
766 if (!isAllowed(f)) {
767 request.setAttribute("dir", f.getParent());
768 request.setAttribute("error", "You are not allowed to access "+f.getAbsolutePath());
769 }
770 else if (f.exists() && f.canRead()) {
771 if (isPacked(f.getName(), false)) {
772 //If zipFile, do nothing here
773 }
774 else{
775 String mimeType = getMimeType(f.getName());
776 response.setContentType(mimeType);
777 if (mimeType.equals("text/plain")) response.setHeader(
778 "Content-Disposition", "inline;filename=\"temp.txt\"");
779 else response.setHeader("Content-Disposition", "inline;filename=\""
780 + f.getName() + "\"");
781 BufferedInputStream fileInput = new BufferedInputStream(new FileInputStream(f));
782 byte buffer[] = new byte[8 * 1024];
783 out.clearBuffer();
784 OutputStream out_s = new Writer2Stream(out);
785 copyStreamsWithoutClose(fileInput, out_s, buffer);
786 fileInput.close();
787 out_s.flush();
788 nohtml = true;
789 dir_view = false;
790 }
791 }
792 else {
793 request.setAttribute("dir", f.getParent());
794 request.setAttribute("error", "File " + f.getAbsolutePath()
795 + " does not exist or is not readable on the server");
796 }
797 }
798 // Download selected files as zip file
799 else if ((request.getParameter("Submit") != null)
800 && (request.getParameter("Submit").equals(SAVE_AS_ZIP))) {
801 Vector v = expandFileList(request.getParameterValues("selfile"), false);
802 //Check if all files in vector are allowed
803 String notAllowedFile = null;
804 for (int i = 0;i < v.size(); i++){
805 File f = (File) v.get(i);
806 if (!isAllowed(f)){
807 notAllowedFile = f.getAbsolutePath();
808 break;
809 }
810 }
811 if (notAllowedFile != null){
812 request.setAttribute("error", "You are not allowed to access " + notAllowedFile);
813 }
814 else if (v.size() == 0) {
815 request.setAttribute("error", "No files selected");
816 }
817 else {
818 File dir_file = new File("" + request.getAttribute("dir"));
819 int dir_l = dir_file.getAbsolutePath().length();
820 response.setContentType("application/zip");
821 response.setHeader("Content-Disposition", "attachment;filename=\"rename_me.zip\"");
822 out.clearBuffer();
823 ZipOutputStream zipout = new ZipOutputStream(new Writer2Stream(out));
824 zipout.setComment("Created by jsp File Browser v. " + VERSION_NR);
825 zipout.setLevel(COMPRESSION_LEVEL);
826 for (int i = 0; i < v.size(); i++) {
827 File f = (File) v.get(i);
828 if (f.canRead()) {
829 zipout.putNextEntry(new ZipEntry(f.getAbsolutePath().substring(dir_l + 1)));
830 BufferedInputStream fr = new BufferedInputStream(new FileInputStream(f));
831 byte buffer[] = new byte[0xffff];
832 copyStreamsWithoutClose(fr, zipout, buffer);
833 /* int b;
834 while ((b=fr.read())!=-1) zipout.write(b);*/
835 fr.close();
836 zipout.closeEntry();
837 }
838 }
839 zipout.finish();
840 out.flush();
841 nohtml = true;
842 dir_view = false;
843 }
844 }
845 // Download file
846 else if (request.getParameter("downfile") != null) {
847 String filePath = request.getParameter("downfile");
848 File f = new File(filePath);
849 if (!isAllowed(f)){
850 request.setAttribute("dir", f.getParent());
851 request.setAttribute("error", "You are not allowed to access " + f.getAbsoluteFile());
852 }
853 else if (f.exists() && f.canRead()) {
854 response.setContentType("application/octet-stream");
855 response.setHeader("Content-Disposition", "attachment;filename=\"" + f.getName()
856 + "\"");
857 response.setContentLength((int) f.length());
858 BufferedInputStream fileInput = new BufferedInputStream(new FileInputStream(f));
859 byte buffer[] = new byte[8 * 1024];
860 out.clearBuffer();
861 OutputStream out_s = new Writer2Stream(out);
862 copyStreamsWithoutClose(fileInput, out_s, buffer);
863 fileInput.close();
864 out_s.flush();
865 nohtml = true;
866 dir_view = false;
867 }
868 else {
869 request.setAttribute("dir", f.getParent());
870 request.setAttribute("error", "File " + f.getAbsolutePath()
871 + " does not exist or is not readable on the server");
872 }
873 }
874 if (nohtml) return;
875 //else
876 // If no parameter is submitted, it will take the path from jsp file browser
877 if (request.getAttribute("dir") == null) {
878 String path = null;
879 if (application.getRealPath(request.getRequestURI()) != null) path = new File(
880 application.getRealPath(request.getRequestURI())).getParent();
881
882 if (path == null) { // handle the case where we are not in a directory (ex: war file)
883 path = new File(".").getAbsolutePath();
884 }
885 //Check path
886 if (!isAllowed(new File(path))){
887 if (RESTRICT_PATH.indexOf(";")<0) path = RESTRICT_PATH;
888 else path = RESTRICT_PATH.substring(0, RESTRICT_PATH.indexOf(";"));
889 }
890 request.setAttribute("dir", path);
891 }%>
892<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
893"http://www.w3.org/TR/html4/loose.dtd">
894<html>
895<head>
896<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
897<meta name="robots" content="noindex">
898<meta http-equiv="expires" content="0">
899<meta http-equiv="pragma" content="no-cache">
900 <style type="text/css">
901 .button {background-color: #c0c0c0; color: #666666;
902 border: 1px solid #999999; }
903 .button:Hover { color: #444444 }
904 table.filelist {background-color:#666666; width:100%; border:0px none #ffffff}
905 th { background-color:#c0c0c0 }
906 tr.mouseout { background-color:#ffffff; }
907 tr.mousein { background-color:#eeeeee; }
908 tr.checked { background-color:#cccccc }
909 tr.mousechecked { background-color:#c0c0c0 }
910 td { font-family:Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; color: #666666;}
911 td.message { background-color: #FFFF00; color: #000000; text-align:center; font-weight:bold}
912 td.error { background-color: #FF0000; color: #000000; text-align:center; font-weight:bold}
913 A { text-decoration: none; }
914 A:Hover { color : Red; text-decoration : underline; }
915 BODY { font-family:Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; color: #666666;}
916 </style>
917 <%
918
919 //Check path
920 if (!isAllowed(new File((String)request.getAttribute("dir")))){
921 request.setAttribute("error", "You are not allowed to access " + request.getAttribute("dir"));
922 }
923 //Upload monitor
924 else if (request.getParameter("uplMonitor") != null) {%>
925 <style type="text/css">
926 BODY { font-family:Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; color: #666666;}
927 </style><%
928 String fname = request.getParameter("uplMonitor");
929 //First opening
930 boolean first = false;
931 if (request.getParameter("first") != null) first = true;
932 UplInfo info = new UplInfo();
933 if (!first) {
934 info = UploadMonitor.getInfo(fname);
935 if (info == null) {
936 //Windows
937 int posi = fname.lastIndexOf("\\");
938 if (posi != -1) info = UploadMonitor.getInfo(fname.substring(posi + 1));
939 }
940 if (info == null) {
941 //Unix
942 int posi = fname.lastIndexOf("/");
943 if (posi != -1) info = UploadMonitor.getInfo(fname.substring(posi + 1));
944 }
945 }
946 dir_view = false;
947 request.setAttribute("dir", null);
948 if (info.aborted) {
949 UploadMonitor.remove(fname);
950 %>
951</head>
952<body>
953<b>Upload of <%=fname%></b><br><br>
954Upload aborted.</body>
955</html><%
956 }
957 else if (info.totalSize != info.currSize || info.currSize == 0) {
958 %>
959<META HTTP-EQUIV="Refresh" CONTENT="<%=UPLOAD_MONITOR_REFRESH%>;URL=<%=browser_name %>?uplMonitor=<%=URLEncoder.encode(fname)%>">
960</head>
961<body>
962<b>Upload of <%=fname%></b><br><br>
963<center>
964<table height="20px" width="90%" bgcolor="#eeeeee" style="border:1px solid #cccccc"><tr>
965<td bgcolor="blue" width="<%=info.getPercent()%>%"></td><td width="<%=100-info.getPercent()%>%"></td>
966</tr></table></center>
967<%=convertFileSize(info.currSize)%> from <%=convertFileSize(info.totalSize)%>
968(<%=info.getPercent()%> %) uploaded (Speed: <%=info.getUprate()%>).<br>
969Time: <%=info.getTimeElapsed()%> from <%=info.getTimeEstimated()%>
970</body>
971</html><%
972 }
973 else {
974 UploadMonitor.remove(fname);
975 %>
976</head>
977<body onload="javascript:window.close()">
978<b>Upload of <%=fname%></b><br><br>
979Upload finished.
980</body>
981</html><%
982 }
983 }
984 //Comandwindow
985 else if (request.getParameter("command") != null) {
986 if (!NATIVE_COMMANDS){
987 request.setAttribute("error", "Execution of native commands is not allowed!");
988 }
989 else if (!"Cancel".equalsIgnoreCase(request.getParameter("Submit"))) {
990%>
991<title>Launch commands in <%=request.getAttribute("dir")%></title>
992</head>
993<body>
994<%
995 out.println("<form action=\"" + browser_name + "\" method=\"Post\">\n"
996 + "<textarea name=\"text\" wrap=\"off\" cols=\"" + EDITFIELD_COLS
997 + "\" rows=\"" + EDITFIELD_ROWS + "\" readonly>");
998 String ret = "";
999 if (!request.getParameter("command").equalsIgnoreCase(""))
1000 ret = startProcess(
1001 request.getParameter("command"), (String) request.getAttribute("dir"));
1002 out.println(ret);
1003%></textarea>
1004 <input type="hidden" name="dir" value="<%= request.getAttribute("dir")%>">
1005 <br>
1006 <table>
1007 <tr><td title="Enter your command">
1008 <input size="<%=EDITFIELD_COLS%>" type="text" name="command" value="">
1009 </td></tr>
1010 <tr><td><input type="Submit" name="Submit" value="Launch">
1011 <input type="hidden" name="sort" value="<%=request.getParameter("sort")%>">
1012 <input type="Submit" name="Submit" value="Cancel"></td></tr>
1013 </table>
1014 </form>
1015</body>
1016</html>
1017<%
1018 dir_view = false;
1019 request.setAttribute("dir", null);
1020 }
1021 }
1022
1023 //Click on a filename, special viewer (zip+jar file)
1024 else if (request.getParameter("file") != null) {
1025 File f = new File(request.getParameter("file"));
1026 if (!isAllowed(f)){
1027 request.setAttribute("error", "You are not allowed to access " + f.getAbsolutePath());
1028 }
1029 else if (isPacked(f.getName(), false)) {
1030 //ZipFile
1031 try {
1032 ZipFile zf = new ZipFile(f);
1033 Enumeration entries = zf.entries();
1034%>
1035<title><%= f.getAbsolutePath()%></title>
1036</head>
1037<body>
1038 <h2>Content of <%=conv2Html(f.getName())%></h2><br>
1039 <table class="filelist" cellspacing="1px" cellpadding="0px">
1040 <th>Name</th><th>Uncompressed size</th><th>Compressed size</th><th>Compr. ratio</th><th>Date</th>
1041<%
1042 long size = 0;
1043 int fileCount = 0;
1044 while (entries.hasMoreElements()) {
1045 ZipEntry entry = (ZipEntry) entries.nextElement();
1046 if (!entry.isDirectory()) {
1047 fileCount++;
1048 size += entry.getSize();
1049 long ratio = 0;
1050 if (entry.getSize() != 0) ratio = (entry.getCompressedSize() * 100)
1051 / entry.getSize();
1052 out.println("<tr class=\"mouseout\"><td>" + conv2Html(entry.getName())
1053 + "</td><td>" + convertFileSize(entry.getSize()) + "</td><td>"
1054 + convertFileSize(entry.getCompressedSize()) + "</td><td>"
1055 + ratio + "%" + "</td><td>"
1056 + dateFormat.format(new Date(entry.getTime())) + "</td></tr>");
1057
1058 }
1059 }
1060 zf.close();
1061 //No directory view
1062 dir_view = false;
1063 request.setAttribute("dir", null);
1064%>
1065 </table>
1066 <p align=center>
1067 <b><%=convertFileSize(size)%> in <%=fileCount%> files in <%=f.getName()%>. Compression ratio: <%=(f.length() * 100) / size%>%
1068 </b></p>
1069</body></html>
1070<%
1071 }
1072 catch (ZipException ex) {
1073 request.setAttribute("error", "Cannot read " + f.getName()
1074 + ", no valid zip file");
1075 }
1076 catch (IOException ex) {
1077 request.setAttribute("error", "Reading of " + f.getName() + " aborted. Error: "
1078 + ex);
1079 }
1080 }
1081 }
1082 // Upload
1083 else if ((request.getContentType() != null)
1084 && (request.getContentType().toLowerCase().startsWith("multipart"))) {
1085 response.setContentType("text/html");
1086 HttpMultiPartParser parser = new HttpMultiPartParser();
1087 boolean error = false;
1088 try {
1089 int bstart = request.getContentType().lastIndexOf("oundary=");
1090 String bound = request.getContentType().substring(bstart + 8);
1091 int clength = request.getContentLength();
1092 Hashtable ht = parser
1093 .processData(request.getInputStream(), bound, tempdir, clength);
1094 if (!isAllowed(new File((String)ht.get("dir")))){
1095 request.setAttribute("error", "You are not allowed to access " + ht.get("dir"));
1096 error = true;
1097 }
1098 else if (ht.get("myFile") != null) {
1099 FileInfo fi = (FileInfo) ht.get("myFile");
1100 File f = fi.file;
1101 UplInfo info = UploadMonitor.getInfo(fi.clientFileName);
1102 if (info != null && info.aborted) {
1103 f.delete();
1104 request.setAttribute("error", "Upload aborted");
1105 }
1106 else {
1107 // Move file from temp to the right dir
1108 String path = (String) ht.get("dir");
1109 if (!path.endsWith(File.separator)) path = path + File.separator;
1110 if (!f.renameTo(new File(path + f.getName()))) {
1111 request.setAttribute("error", "Cannot upload file.");
1112 error = true;
1113 f.delete();
1114 }
1115 }
1116 }
1117 else {
1118 request.setAttribute("error", "No file selected for upload");
1119 error = true;
1120 }
1121 request.setAttribute("dir", (String) ht.get("dir"));
1122 }
1123 catch (Exception e) {
1124 request.setAttribute("error", "Error " + e + ". Upload aborted");
1125 error = true;
1126 }
1127 if (!error) request.setAttribute("message", "File upload correctly finished.");
1128 }
1129 // The form to edit a text file
1130 else if (request.getParameter("editfile") != null) {
1131 File ef = new File(request.getParameter("editfile"));
1132 if (!isAllowed(ef)){
1133 request.setAttribute("error", "You are not allowed to access " + ef.getAbsolutePath());
1134 }
1135 else{
1136%>
1137<title>Edit <%=conv2Html(request.getParameter("editfile"))%></title>
1138</head>
1139<body>
1140<%
1141 BufferedReader reader = new BufferedReader(new FileReader(ef));
1142 String disable = "";
1143 if (!ef.canWrite()) disable = " readonly";
1144 out.println("<form action=\"" + browser_name + "\" method=\"Post\">\n"
1145 + "<textarea name=\"text\" wrap=\"off\" cols=\"" + EDITFIELD_COLS
1146 + "\" rows=\"" + EDITFIELD_ROWS + "\"" + disable + ">");
1147 String c;
1148 // Write out the file and check if it is a win or unix file
1149 int i;
1150 boolean dos = false;
1151 boolean cr = false;
1152 while ((i = reader.read()) >= 0) {
1153 out.print(conv2Html(i));
1154 if (i == '\r') cr = true;
1155 else if (cr && (i == '\n')) dos = true;
1156 else cr = false;
1157 }
1158 reader.close();
1159 //No File directory is shown
1160 request.setAttribute("dir", null);
1161 dir_view = false;
1162
1163%></textarea>
1164 <input type="hidden" name="nfile" value="<%= request.getParameter("editfile")%>">
1165 <br>
1166 <table>
1167 <tr><td><input type="radio" name="lineformat" value="dos" <%= dos?"checked":""%>>Ms-Dos/Windows</td>
1168 <td><input type="radio" name="lineformat" value="unix" <%= dos?"":"checked"%>>Unix</td>
1169 <td><input type="checkbox" name="Backup" checked>Write backup</td></tr>
1170 <tr><td title="Enter the new filename"><input type="text" name="new_name" value="<%=ef.getName()%>"></td>
1171 <td><input type="Submit" name="Submit" value="Save"></td>
1172 <td><input type="Submit" name="Submit" value="Cancel">
1173 <input type="hidden" name="sort" value="<%=request.getParameter("sort")%>">
1174 </td></tr>
1175 </table>
1176 </form>
1177</body>
1178</html>
1179<%
1180 }
1181 }
1182 // Save or cancel the edited file
1183 else if (request.getParameter("nfile") != null) {
1184 File f = new File(request.getParameter("nfile"));
1185 File new_f = new File(getDir(f.getParent(), request.getParameter("new_name")));
1186 if (!isAllowed(new_f)){
1187 request.setAttribute("error", "You are not allowed to access " + new_f.getAbsolutePath());
1188 }
1189 else if (request.getParameter("Submit").equals("Save")) {
1190 if (new_f.exists() && new_f.canWrite() && request.getParameter("Backup") != null) {
1191 File bak = new File(new_f.getAbsolutePath() + ".bak");
1192 bak.delete();
1193 new_f.renameTo(bak);
1194 }
1195 if (new_f.exists() && !new_f.canWrite()) request.setAttribute("error",
1196 "Cannot write to " + new_f.getName() + ", file is write protected.");
1197 else {
1198 BufferedWriter outs = new BufferedWriter(new FileWriter(new_f));
1199 StringReader text = new StringReader(request.getParameter("text"));
1200 int i;
1201 boolean cr = false;
1202 String lineend = "\n";
1203 if (request.getParameter("lineformat").equals("dos")) lineend = "\r\n";
1204 while ((i = text.read()) >= 0) {
1205 if (i == '\r') cr = true;
1206 else if (i == '\n') {
1207 outs.write(lineend);
1208 cr = false;
1209 }
1210 else if (cr) {
1211 outs.write(lineend);
1212 cr = false;
1213 }
1214 else {
1215 outs.write(i);
1216 cr = false;
1217 }
1218 }
1219 outs.flush();
1220 outs.close();
1221 }
1222 }
1223 request.setAttribute("dir", f.getParent());
1224 }
1225 //Unpack file to the current directory without overwriting
1226 else if (request.getParameter("unpackfile") != null) {
1227 File f = new File(request.getParameter("unpackfile"));
1228 String root = f.getParent();
1229 request.setAttribute("dir", root);
1230 if (!isAllowed(new File(root))){
1231 request.setAttribute("error", "You are not allowed to access " + root);
1232 }
1233 //Check if file exists
1234 else if (!f.exists()) {
1235 request.setAttribute("error", "Cannot unpack " + f.getName()
1236 + ", file does not exist");
1237 }
1238 //Check if directory is readonly
1239 else if (!f.getParentFile().canWrite()) {
1240 request.setAttribute("error", "Cannot unpack " + f.getName()
1241 + ", directory is write protected.");
1242 }
1243 //GZip
1244 else if (f.getName().toLowerCase().endsWith(".gz")) {
1245 //New name is old Name without .gz
1246 String newName = f.getAbsolutePath().substring(0, f.getAbsolutePath().length() - 3);
1247 try {
1248 byte buffer[] = new byte[0xffff];
1249 copyStreams(new GZIPInputStream(new FileInputStream(f)), new FileOutputStream(
1250 newName), buffer);
1251 }
1252 catch (IOException ex) {
1253 request.setAttribute("error", "Unpacking of " + f.getName()
1254 + " aborted. Error: " + ex);
1255 }
1256 }
1257 //Else try Zip
1258 else {
1259 try {
1260 ZipFile zf = new ZipFile(f);
1261 Enumeration entries = zf.entries();
1262 //First check whether a file already exist
1263 boolean error = false;
1264 while (entries.hasMoreElements()) {
1265 ZipEntry entry = (ZipEntry) entries.nextElement();
1266 if (!entry.isDirectory()
1267 && new File(root + File.separator + entry.getName()).exists()) {
1268 request.setAttribute("error", "Cannot unpack " + f.getName()
1269 + ", File " + entry.getName() + " already exists.");
1270 error = true;
1271 break;
1272 }
1273 }
1274 if (!error) {
1275 //Unpack File
1276 entries = zf.entries();
1277 byte buffer[] = new byte[0xffff];
1278 while (entries.hasMoreElements()) {
1279 ZipEntry entry = (ZipEntry) entries.nextElement();
1280 File n = new File(root + File.separator + entry.getName());
1281 if (entry.isDirectory()) n.mkdirs();
1282 else {
1283 n.getParentFile().mkdirs();
1284 n.createNewFile();
1285 copyStreams(zf.getInputStream(entry), new FileOutputStream(n),
1286 buffer);
1287 }
1288 }
1289 zf.close();
1290 request.setAttribute("message", "Unpack of " + f.getName()
1291 + " was successful.");
1292 }
1293 }
1294 catch (ZipException ex) {
1295 request.setAttribute("error", "Cannot unpack " + f.getName()
1296 + ", no valid zip file");
1297 }
1298 catch (IOException ex) {
1299 request.setAttribute("error", "Unpacking of " + f.getName()
1300 + " aborted. Error: " + ex);
1301 }
1302 }
1303 }
1304 // Delete Files
1305 else if ((request.getParameter("Submit") != null)
1306 && (request.getParameter("Submit").equals(DELETE_FILES))) {
1307 Vector v = expandFileList(request.getParameterValues("selfile"), true);
1308 boolean error = false;
1309 //delete backwards
1310 for (int i = v.size() - 1; i >= 0; i--) {
1311 File f = (File) v.get(i);
1312 if (!isAllowed(f)){
1313 request.setAttribute("error", "You are not allowed to access " + f.getAbsolutePath());
1314 error = true;
1315 break;
1316 }
1317 if (!f.canWrite() || !f.delete()) {
1318 request.setAttribute("error", "Cannot delete " + f.getAbsolutePath()
1319 + ". Deletion aborted");
1320 error = true;
1321 break;
1322 }
1323 }
1324 if ((!error) && (v.size() > 1)) request.setAttribute("message", "All files deleted");
1325 else if ((!error) && (v.size() > 0)) request.setAttribute("message", "File deleted");
1326 else if (!error) request.setAttribute("error", "No files selected");
1327 }
1328 // Create Directory
1329 else if ((request.getParameter("Submit") != null)
1330 && (request.getParameter("Submit").equals(CREATE_DIR))) {
1331 String dir = "" + request.getAttribute("dir");
1332 String dir_name = request.getParameter("cr_dir");
1333 String new_dir = getDir(dir, dir_name);
1334 if (!isAllowed(new File(new_dir))){
1335 request.setAttribute("error", "You are not allowed to access " + new_dir);
1336 }
1337 else if (new File(new_dir).mkdirs()) {
1338 request.setAttribute("message", "Directory created");
1339 }
1340 else request.setAttribute("error", "Creation of directory " + new_dir + " failed");
1341 }
1342 // Create a new empty file
1343 else if ((request.getParameter("Submit") != null)
1344 && (request.getParameter("Submit").equals(CREATE_FILE))) {
1345 String dir = "" + request.getAttribute("dir");
1346 String file_name = request.getParameter("cr_dir");
1347 String new_file = getDir(dir, file_name);
1348 if (!isAllowed(new File(new_file))){
1349 request.setAttribute("error", "You are not allowed to access " + new_file);
1350 }
1351 // Test, if file_name is empty
1352 else if (!"".equals(file_name.trim()) && !file_name.endsWith(File.separator)) {
1353 if (new File(new_file).createNewFile()) request.setAttribute("message",
1354 "File created");
1355 else request.setAttribute("error", "Creation of file " + new_file + " failed");
1356 }
1357 else request.setAttribute("error", "Error: " + file_name + " is not a valid filename");
1358 }
1359 // Rename a file
1360 else if ((request.getParameter("Submit") != null)
1361 && (request.getParameter("Submit").equals(RENAME_FILE))) {
1362 Vector v = expandFileList(request.getParameterValues("selfile"), true);
1363 String dir = "" + request.getAttribute("dir");
1364 String new_file_name = request.getParameter("cr_dir");
1365 String new_file = getDir(dir, new_file_name);
1366 if (!isAllowed(new File(new_file))){
1367 request.setAttribute("error", "You are not allowed to access " + new_file);
1368 }
1369 // The error conditions:
1370 // 1) Zero Files selected
1371 else if (v.size() <= 0) request.setAttribute("error",
1372 "Select exactly one file or folder. Rename failed");
1373 // 2a) Multiple files selected and the first isn't a dir
1374 // Here we assume that expandFileList builds v from top-bottom, starting with the dirs
1375 else if ((v.size() > 1) && !(((File) v.get(0)).isDirectory())) request.setAttribute(
1376 "error", "Select exactly one file or folder. Rename failed");
1377 // 2b) If there are multiple files from the same directory, rename fails
1378 else if ((v.size() > 1) && ((File) v.get(0)).isDirectory()
1379 && !(((File) v.get(0)).getPath().equals(((File) v.get(1)).getParent()))) {
1380 request.setAttribute("error", "Select exactly one file or folder. Rename failed");
1381 }
1382 else {
1383 File f = (File) v.get(0);
1384 if (!isAllowed(f)){
1385 request.setAttribute("error", "You are not allowed to access " + f.getAbsolutePath());
1386 }
1387 // Test, if file_name is empty
1388 else if ((new_file.trim() != "") && !new_file.endsWith(File.separator)) {
1389 if (!f.canWrite() || !f.renameTo(new File(new_file.trim()))) {
1390 request.setAttribute("error", "Creation of file " + new_file + " failed");
1391 }
1392 else request.setAttribute("message", "Renamed file "
1393 + ((File) v.get(0)).getName() + " to " + new_file);
1394 }
1395 else request.setAttribute("error", "Error: \"" + new_file_name
1396 + "\" is not a valid filename");
1397 }
1398 }
1399 // Move selected file(s)
1400 else if ((request.getParameter("Submit") != null)
1401 && (request.getParameter("Submit").equals(MOVE_FILES))) {
1402 Vector v = expandFileList(request.getParameterValues("selfile"), true);
1403 String dir = "" + request.getAttribute("dir");
1404 String dir_name = request.getParameter("cr_dir");
1405 String new_dir = getDir(dir, dir_name);
1406 if (!isAllowed(new File(new_dir))){
1407 request.setAttribute("error", "You are not allowed to access " + new_dir);
1408 }
1409 else{
1410 boolean error = false;
1411 // This ensures that new_dir is a directory
1412 if (!new_dir.endsWith(File.separator)) new_dir += File.separator;
1413 for (int i = v.size() - 1; i >= 0; i--) {
1414 File f = (File) v.get(i);
1415 if (!isAllowed(f)){
1416 request.setAttribute("error", "You are not allowed to access " + f.getAbsolutePath());
1417 error = true;
1418 break;
1419 }
1420 else if (!f.canWrite() || !f.renameTo(new File(new_dir
1421 + f.getAbsolutePath().substring(dir.length())))) {
1422 request.setAttribute("error", "Cannot move " + f.getAbsolutePath()
1423 + ". Move aborted");
1424 error = true;
1425 break;
1426 }
1427 }
1428 if ((!error) && (v.size() > 1)) request.setAttribute("message", "All files moved");
1429 else if ((!error) && (v.size() > 0)) request.setAttribute("message", "File moved");
1430 else if (!error) request.setAttribute("error", "No files selected");
1431 }
1432 }
1433 // Copy Files
1434 else if ((request.getParameter("Submit") != null)
1435 && (request.getParameter("Submit").equals(COPY_FILES))) {
1436 Vector v = expandFileList(request.getParameterValues("selfile"), true);
1437 String dir = (String) request.getAttribute("dir");
1438 if (!dir.endsWith(File.separator)) dir += File.separator;
1439 String dir_name = request.getParameter("cr_dir");
1440 String new_dir = getDir(dir, dir_name);
1441 if (!isAllowed(new File(new_dir))){
1442 request.setAttribute("error", "You are not allowed to access " + new_dir);
1443 }
1444 else{
1445 boolean error = false;
1446 if (!new_dir.endsWith(File.separator)) new_dir += File.separator;
1447 try {
1448 byte buffer[] = new byte[0xffff];
1449 for (int i = 0; i < v.size(); i++) {
1450 File f_old = (File) v.get(i);
1451 File f_new = new File(new_dir + f_old.getAbsolutePath().substring(dir.length()));
1452 if (!isAllowed(f_old)|| !isAllowed(f_new)){
1453 request.setAttribute("error", "You are not allowed to access " + f_new.getAbsolutePath());
1454 error = true;
1455 }
1456 else if (f_old.isDirectory()) f_new.mkdirs();
1457 // Overwriting is forbidden
1458 else if (!f_new.exists()) {
1459 copyStreams(new FileInputStream(f_old), new FileOutputStream(f_new), buffer);
1460 }
1461 else {
1462 // File exists
1463 request.setAttribute("error", "Cannot copy " + f_old.getAbsolutePath()
1464 + ", file already exists. Copying aborted");
1465 error = true;
1466 break;
1467 }
1468 }
1469 }
1470 catch (IOException e) {
1471 request.setAttribute("error", "Error " + e + ". Copying aborted");
1472 error = true;
1473 }
1474 if ((!error) && (v.size() > 1)) request.setAttribute("message", "All files copied");
1475 else if ((!error) && (v.size() > 0)) request.setAttribute("message", "File copied");
1476 else if (!error) request.setAttribute("error", "No files selected");
1477 }
1478 }
1479 // Directory viewer
1480 if (dir_view && request.getAttribute("dir") != null) {
1481 File f = new File("" + request.getAttribute("dir"));
1482 //Check, whether the dir exists
1483 if (!f.exists() || !isAllowed(f)) {
1484 if (!f.exists()){
1485 request.setAttribute("error", "Directory " + f.getAbsolutePath() + " does not exist.");
1486 }
1487 else{
1488 request.setAttribute("error", "You are not allowed to access " + f.getAbsolutePath());
1489 }
1490 //if attribute olddir exists, it will change to olddir
1491 if (request.getAttribute("olddir") != null && isAllowed(new File((String) request.getAttribute("olddir")))) {
1492 f = new File("" + request.getAttribute("olddir"));
1493 }
1494 //try to go to the parent dir
1495 else {
1496 if (f.getParent() != null && isAllowed(f)) f = new File(f.getParent());
1497 }
1498 //If this dir also do also not exist, go back to browser.jsp root path
1499 if (!f.exists()) {
1500 String path = null;
1501 if (application.getRealPath(request.getRequestURI()) != null) path = new File(
1502 application.getRealPath(request.getRequestURI())).getParent();
1503
1504 if (path == null) // handle the case were we are not in a directory (ex: war file)
1505 path = new File(".").getAbsolutePath();
1506 f = new File(path);
1507 }
1508 if (isAllowed(f)) request.setAttribute("dir", f.getAbsolutePath());
1509 else request.setAttribute("dir", null);
1510 }
1511%>
1512<script type="text/javascript">
1513<!--
1514 <%// This section contains the Javascript used for interface elements %>
1515 var check = false;
1516 <%// Disables the checkbox feature %>
1517 function dis(){check = true;}
1518
1519 var DOM = 0, MS = 0, OP = 0, b = 0;
1520 <%// Determine the browser type %>
1521 function CheckBrowser(){
1522 if (b == 0){
1523 if (window.opera) OP = 1;
1524 // Moz or Netscape
1525 if(document.getElementById) DOM = 1;
1526 // Micro$oft
1527 if(document.all && !OP) MS = 1;
1528 b = 1;
1529 }
1530 }
1531 <%// Allows the whole row to be selected %>
1532 function selrow (element, i){
1533 var erst;
1534 CheckBrowser();
1535 if ((OP==1)||(MS==1)) erst = element.firstChild.firstChild;
1536 else if (DOM==1) erst = element.firstChild.nextSibling.firstChild;
1537 <%// MouseIn %>
1538 if (i==0){
1539 if (erst.checked == true) element.className='mousechecked';
1540 else element.className='mousein';
1541 }
1542 <%// MouseOut %>
1543 else if (i==1){
1544 if (erst.checked == true) element.className='checked';
1545 else element.className='mouseout';
1546 }
1547 <% // MouseClick %>
1548 else if ((i==2)&&(!check)){
1549 if (erst.checked==true) element.className='mousein';
1550 else element.className='mousechecked';
1551 erst.click();
1552 }
1553 else check=false;
1554 }
1555 <%//(De)select all checkboxes%>
1556 function AllFiles(){
1557 for(var x=0;x<document.FileList.elements.length;x++){
1558 var y = document.FileList.elements[x];
1559 var ytr = y.parentNode.parentNode;
1560 var check = document.FileList.selall.checked;
1561 if(y.name == 'selfile'){
1562 if (y.disabled != true){
1563 y.checked = check;
1564 if (y.checked == true) ytr.className = 'checked';
1565 else ytr.className = 'mouseout';
1566 }
1567 }
1568 }
1569 }
1570
1571 function popUp(URL){
1572 fname = document.getElementsByName("myFile")[0].value;
1573 if (fname != "")
1574 window.open(URL+"?first&uplMonitor="+encodeURIComponent(fname),"","width=400,height=150,resizable=yes,depend=yes")
1575 }
1576//-->
1577</script>
1578<title><%=request.getAttribute("dir")%></title>
1579</head>
1580<body>
1581<%
1582 //Output message
1583 if (request.getAttribute("message") != null) {
1584 out.println("<table border=\"0\" width=\"100%\"><tr><td class=\"message\">");
1585 out.println(request.getAttribute("message"));
1586 out.println("</td></tr></table>");
1587 }
1588 //Output error
1589 if (request.getAttribute("error") != null) {
1590 out.println("<table border=\"0\" width=\"100%\"><tr><td class=\"error\">");
1591 out.println(request.getAttribute("error"));
1592 out.println("</td></tr></table>");
1593 }
1594 if (request.getAttribute("dir") != null){
1595%>
1596 <form action="<%= browser_name %>" method="Post" name="FileList">
1597 <table class="filelist" cellspacing="1px" cellpadding="0px">
1598<%
1599 // Output the table, starting with the headers.
1600 String dir = URLEncoder.encode("" + request.getAttribute("dir"));
1601 String cmd = browser_name + "?dir=" + dir;
1602 int sortMode = 1;
1603 if (request.getParameter("sort") != null) sortMode = Integer.parseInt(request
1604 .getParameter("sort"));
1605 int[] sort = new int[] {1, 2, 3, 4};
1606 for (int i = 0; i < sort.length; i++)
1607 if (sort[i] == sortMode) sort[i] = -sort[i];
1608 out.println("<tr><th> </th><th title=\"Sort files by name\" align=left><a href=\""
1609 + cmd + "&sort=" + sort[0] + "\">Name</a></th>"
1610 + "<th title=\"Sort files by size\" align=\"right\"><a href=\"" + cmd
1611 + "&sort=" + sort[1] + "\">Size</a></th>"
1612 + "<th title=\"Sort files by type\" align=\"center\"><a href=\"" + cmd
1613 + "&sort=" + sort[3] + "\">Type</a></th>"
1614 + "<th title=\"Sort files by date\" align=\"left\"><a href=\"" + cmd
1615 + "&sort=" + sort[2] + "\">Date</a></th>"
1616 + "<th> </th><th> </th></tr>");
1617 char trenner = File.separatorChar;
1618 // Output the Root-Dirs, without FORBIDDEN_DRIVES
1619 File[] entry = File.listRoots();
1620 for (int i = 0; i < entry.length; i++) {
1621 boolean forbidden = false;
1622 for (int i2 = 0; i2 < FORBIDDEN_DRIVES.length; i2++) {
1623 if (entry[i].getAbsolutePath().toLowerCase().equals(FORBIDDEN_DRIVES[i2])) forbidden = true;
1624 }
1625 if (!forbidden) {
1626 out.println("<tr class=\"mouseout\" onmouseover=\"this.className='mousein'\""
1627 + "onmouseout=\"this.className='mouseout'\">");
1628 out.println("<td> </td><td align=left >");
1629 String name = URLEncoder.encode(entry[i].getAbsolutePath());
1630 String buf = entry[i].getAbsolutePath();
1631 out.println(" <a href=\"" + browser_name + "?sort=" + sortMode
1632 + "&dir=" + name + "\">[" + buf + "]</a>");
1633 out
1634 .println("</td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>");
1635 }
1636 }
1637 // Output the parent directory link ".."
1638 if (f.getParent() != null) {
1639 out.println("<tr class=\"mouseout\" onmouseover=\"this.className='mousein'\""
1640 + "onmouseout=\"this.className='mouseout'\">");
1641 out.println("<td></td><td align=left>");
1642 out.println(" <a href=\"" + browser_name + "?sort=" + sortMode + "&dir="
1643 + URLEncoder.encode(f.getParent()) + "\">" + FOL_IMG + "[..]</a>");
1644 out
1645 .println("</td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>");
1646 }
1647 // Output all files and dirs and calculate the number of files and total size
1648 entry = f.listFiles();
1649 if (entry == null) entry = new File[] {};
1650 long totalSize = 0; // The total size of the files in the current directory
1651 long fileCount = 0; // The count of files in the current working directory
1652 if (entry != null && entry.length > 0) {
1653 Arrays.sort(entry, new FileComp(sortMode));
1654 for (int i = 0; i < entry.length; i++) {
1655 String name = URLEncoder.encode(entry[i].getAbsolutePath());
1656 String type = "File"; // This String will tell the extension of the file
1657 if (entry[i].isDirectory()) type = "DIR"; // It's a DIR
1658 else {
1659 String tempName = entry[i].getName().replace(' ', '_');
1660 if (tempName.lastIndexOf('.') != -1) type = tempName.substring(
1661 tempName.lastIndexOf('.')).toLowerCase();
1662 }
1663 String ahref = "<a onmousedown=\"dis()\" href=\"" + browser_name + "?sort="
1664 + sortMode + "&";
1665 String dlink = " "; // The "Download" link
1666 String elink = " "; // The "Edit" link
1667 String buf = conv2Html(entry[i].getName());
1668 if (!entry[i].canWrite()) buf = "<i>" + buf + "</i>";
1669 String link = buf; // The standard view link, uses Mime-type
1670 if (entry[i].isDirectory()) {
1671 if (entry[i].canRead() && USE_DIR_PREVIEW) {
1672 //Show the first DIR_PREVIEW_NUMBER directory entries in a tooltip
1673 File[] fs = entry[i].listFiles();
1674 if (fs == null) fs = new File[] {};
1675 Arrays.sort(fs, new FileComp());
1676 StringBuffer filenames = new StringBuffer();
1677 for (int i2 = 0; (i2 < fs.length) && (i2 < 10); i2++) {
1678 String fname = conv2Html(fs[i2].getName());
1679 if (fs[i2].isDirectory()) filenames.append("[" + fname + "];");
1680 else filenames.append(fname + ";");
1681 }
1682 if (fs.length > DIR_PREVIEW_NUMBER) filenames.append("...");
1683 else if (filenames.length() > 0) filenames
1684 .setLength(filenames.length() - 1);
1685 link = ahref + "dir=" + name + "\" title=\"" + filenames + "\">"
1686 + FOL_IMG + "[" + buf + "]</a>";
1687 }
1688 else if (entry[i].canRead()) {
1689 link = ahref + "dir=" + name + "\">" + FOL_IMG + "[" + buf + "]</a>";
1690 }
1691 else link = FOL_IMG + "[" + buf + "]";
1692 }
1693 else if (entry[i].isFile()) { //Entry is file
1694 totalSize = totalSize + entry[i].length();
1695 fileCount = fileCount + 1;
1696 if (entry[i].canRead()) {
1697 dlink = ahref + "downfile=" + name + "\">Download</a>";
1698 //If you click at the filename
1699 if (USE_POPUP) link = ahref + "file=" + name + "\" target=\"_blank\">"
1700 + buf + "</a>";
1701 else link = ahref + "file=" + name + "\">" + buf + "</a>";
1702 if (entry[i].canWrite()) { // The file can be edited
1703 //If it is a zip or jar File you can unpack it
1704 if (isPacked(name, true)) elink = ahref + "unpackfile=" + name
1705 + "\">Unpack</a>";
1706 else elink = ahref + "editfile=" + name + "\">Edit</a>";
1707 }
1708 else { // If the file cannot be edited
1709 //If it is a zip or jar File you can unpack it
1710 if (isPacked(name, true)) elink = ahref + "unpackfile=" + name
1711 + "\">Unpack</a>";
1712 else elink = ahref + "editfile=" + name + "\">View</a>";
1713 }
1714 }
1715 else {
1716 link = buf;
1717 }
1718 }
1719 String date = dateFormat.format(new Date(entry[i].lastModified()));
1720 out.println("<tr class=\"mouseout\" onmouseup=\"selrow(this, 2)\" "
1721 + "onmouseover=\"selrow(this, 0);\" onmouseout=\"selrow(this, 1)\">");
1722 if (entry[i].canRead()) {
1723 out
1724 .println("<td align=center><input type=\"checkbox\" name=\"selfile\" value=\""
1725 + name + "\" onmousedown=\"dis()\"></td>");
1726 }
1727 else {
1728 out
1729 .println("<td align=center><input type=\"checkbox\" name=\"selfile\" disabled></td>");
1730 }
1731 out.print("<td align=left> " + link + "</td>");
1732 if (entry[i].isDirectory()) out.print("<td> </td>");
1733 else {
1734 out.print("<td align=right title=\"" + entry[i].length() + " bytes\">"
1735 + convertFileSize(entry[i].length()) + "</td>");
1736 }
1737 out.println("<td align=\"center\">" + type + "</td><td align=left> " + // The file type (extension)
1738 date + "</td><td>" + // The date the file was created
1739 dlink + "</td><td>" + // The download link
1740 elink + "</td></tr>"); // The edit link (or view, depending)
1741 }
1742 }%>
1743 </table>
1744 <input type="checkbox" name="selall" onClick="AllFiles(this.form)">Select all
1745 <p align=center>
1746 <b title="<%=totalSize%> bytes">
1747 <%=convertFileSize(totalSize)%></b><b> in <%=fileCount%> files in <%= dir2linkdir((String) request.getAttribute("dir"), browser_name, sortMode)%>
1748 </b>
1749 </p>
1750 <p>
1751 <input type="hidden" name="dir" value="<%=request.getAttribute("dir")%>">
1752 <input type="hidden" name="sort" value="<%=sortMode%>">
1753 <input title="Download selected files and directories as one zip file" class="button" type="Submit" name="Submit" value="<%=SAVE_AS_ZIP%>">
1754 <input title="Delete all selected files and directories incl. subdirs" class="button" type="Submit" name="Submit" value="<%=DELETE_FILES%>"
1755 onclick="return confirm('Do you really want to delete the entries?')">
1756 </p>
1757 <p>
1758 <input title="Enter new dir or filename or the relative or absolute path" type="text" name="cr_dir">
1759 <input title="Create a new directory with the given name" class="button" type="Submit" name="Submit" value="<%=CREATE_DIR%>">
1760 <input title="Create a new empty file with the given name" class="button" type="Submit" name="Submit" value="<%=CREATE_FILE%>">
1761 <input title="Move selected files and directories to the entered path" class="button" type="Submit" name="Submit" value="<%=MOVE_FILES%>">
1762 <input title="Copy selected files and directories to the entered path" class="button" type="Submit" name="Submit" value="<%=COPY_FILES%>">
1763 <input title="Rename selected file or directory to the entered name" class="button" type="Submit" name="Submit" value="<%=RENAME_FILE%>">
1764 </p>
1765 </form>
1766 <form action="<%= browser_name%>" enctype="multipart/form-data" method="POST">
1767 <input type="hidden" name="dir" value="<%=request.getAttribute("dir")%>">
1768 <input type="hidden" name="sort" value="<%=sortMode%>">
1769 <input type="file" name="myFile">
1770 <input title="Upload selected file to the current working directory" type="Submit" class="button" name="Submit" value="Upload"
1771 onClick="javascript:popUp('<%= browser_name%>')">
1772 </form>
1773 <% if (NATIVE_COMMANDS){%>
1774 <form action="<%= browser_name%>" method="POST">
1775 <input type="hidden" name="dir" value="<%=request.getAttribute("dir")%>">
1776 <input type="hidden" name="sort" value="<%=sortMode%>">
1777 <input type="hidden" name="command" value="">
1778 <input title="Launch command in current directory" type="Submit" class="button" name="Submit" value="Launch command">
1779 </form><%
1780 }
1781 }%>
1782 <hr>
1783 <center>
1784 <small>jsp File Browser version <%= VERSION_NR%> by <a href="http://www.vonloesch.de">www.vonloesch.de</a></small>
1785 </center>
1786</body>
1787</html><%
1788 }
1789%>