2 import java.awt.event.*;
7 import netscape.javascript.JSObject;
9 // A java filemanager that allows the user to manipulate files on the
10 // Webmin server. Layout is similar to the windows explorer - directory
11 // tree on the left, files on the right, action buttons on the top.
12 public class FileManager extends Applet
13 implements CbButtonCallback, HierarchyCallback, MultiColumnCallback
16 CbButton ret_b, config_b, down_b, edit_b, refresh_b, props_b,
17 copy_b, cut_b, paste_b, delete_b, new_b, upload_b, mkdir_b,
18 makelink_b, rename_b, share_b, mount_b, search_b, acl_b,
19 attr_b, ext_b, preview_b, extract_b, hnew_b;
24 Hashtable nodemap = new Hashtable();
30 RemoteFile showing_files;
31 RemoteFile showing_list[];
32 Vector history_list = new Vector();
34 // Copying and pasting
35 RemoteFile cut_buffer[];
38 static final String monmap[] = { "Jan", "Feb", "Mar", "Apr",
39 "May", "Jun", "Jul", "Aug",
40 "Sep", "Oct", "Nov", "Dec" };
43 Hashtable lang = new Hashtable();
44 Hashtable stab = new Hashtable(),
45 ntab = new Hashtable();
53 boolean got_filesystems,
54 acl_support, attr_support, ext_support;
55 Hashtable mounts = new Hashtable();
56 Vector fslist = new Vector();
57 boolean read_only = false;
59 // Standard font for all text
62 // Font for button labels
65 // Full session cookie
74 // Chroot directory for tree
77 // File attributes that can be edited
78 boolean can_perms, can_users;
80 // Symlimks are automatically followed
83 // Can search file contents
84 boolean search_contents;
86 // Use text editor for HTML
89 // File extensions to consider as HTML
94 setLayout(new BorderLayout());
96 // Create fonts from specified size
97 fixed = make_font("fixed", 12);
98 small_fixed = make_font("small_fixed", 10);
100 Util.setFont(small_fixed);
101 StringTokenizer tok = new StringTokenizer(getParameter("root"), " ");
102 accroot = new String[tok.countTokens()];
103 for(int i=0; tok.hasMoreTokens(); i++)
104 accroot[i] = tok.nextToken();
105 if (getParameter("noroot") != null) {
106 tok = new StringTokenizer(getParameter("noroot"), " ");
107 accnoroot = new String[tok.countTokens()];
108 for(int i=0; tok.hasMoreTokens(); i++)
109 accnoroot[i] = tok.nextToken();
112 accnoroot = new String[0];
114 trust = getParameter("trust");
115 session = getParameter("session");
116 referer = getDocumentBase().toString();
117 extra = getParameter("extra");
118 if (extra == null) extra = "";
119 images = getParameter("images");
120 if (images == null) images = "images";
121 iconsize = Integer.parseInt(getParameter("iconsize"));
122 archive = getParameter("doarchive");
123 if (archive == null) archive = "0";
124 chroot = getParameter("chroot");
125 if (chroot == null) chroot = "/";
126 String can_perms_str = getParameter("canperms");
127 can_perms = can_perms_str == null || !can_perms_str.equals("0");
128 String can_users_str = getParameter("canusers");
129 can_users = can_users_str == null || !can_users_str.equals("0");
130 String search_contents_str = getParameter("contents");
131 search_contents = search_contents_str == null ||
132 !search_contents_str.equals("0");
133 String force_text_str = getParameter("force_text");
134 if (force_text_str != null && force_text_str.equals("1"))
136 String htmlexts_str = getParameter("htmlexts");
137 if (htmlexts_str == null || htmlexts_str.equals(""))
138 htmlexts_str = ".htm .html";
139 htmlexts = DFSAdminExport.split(htmlexts_str);
141 // download language strings
142 String l[] = get_text("lang.cgi");
143 if (l.length < 1 || l[0].indexOf('=') < 0) {
144 String err = "Failed to get language list : "+join_array(l);
145 new ErrorWindow(err);
146 throw new Error(err);
148 for(int i=0; i<l.length; i++) {
149 int eq = l[i].indexOf('=');
151 lang.put(l[i].substring(0, eq), l[i].substring(eq+1));
154 // list samba file shares
155 String s[] = get_text("list_shares.cgi");
156 if (s[0].equals("1")) {
157 for(int i=1; i<s.length; i++) {
158 SambaShare ss = new SambaShare(s[i]);
159 stab.put(ss.path, ss);
165 String e[] = get_text("list_exports.cgi");
166 nfsmode = e.length == 0 ? 0 : Integer.parseInt(e[0]);
168 for(int i=1; i<e.length; i++) {
171 LinuxExport le = new LinuxExport(e[i]);
172 ntab.put(le.path, le);
174 else if (nfsmode == 2) {
176 DFSAdminExport de = new DFSAdminExport(e[i]);
177 ntab.put(de.path, de);
185 // get read-only flag
186 if (getParameter("ro").equals("1"))
189 // get custom colours
190 Util.light_edge = get_colour("light_edge", Util.light_edge);
191 Util.dark_edge = get_colour("dark_edge", Util.dark_edge);
192 Util.body = get_colour("body", Util.body);
193 Util.body_hi = get_colour("body_hi", Util.body_hi);
194 Util.light_edge_hi = get_colour("light_edge_hi", Util.light_edge_hi);
195 Util.dark_edge_hi = get_colour("dark_edge_hi", Util.dark_edge_hi);
196 Util.dark_bg = get_colour("dark_bg", Util.dark_bg);
197 Util.text = get_colour("text", Util.text);
198 Util.light_bg = get_colour("light_bg", Util.light_bg);
200 // create button panel
201 BorderPanel top = new BorderPanel(2, Util.body);
202 top.setLayout(new ToolbarLayout(ToolbarLayout.LEFT, 5, 2));
204 Panel top1 = new Panel();
205 top1.setLayout(new GridLayout(1, 0));
206 if (getParameter("return") != null && can_button("return"))
207 top1.add(ret_b = make_button("ret.gif", text("top_ret")));
208 if (getParameter("config") != null && can_button("config"))
209 top1.add(config_b = make_button("config.gif",
210 text("top_config")));
211 if (can_button("save"))
212 top1.add(down_b = make_button("down.gif", text("top_down")));
213 if (can_button("preview"))
214 top1.add(preview_b = make_button("preview.gif", text("top_preview")));
215 if (!read_only && can_button("edit")) {
216 top1.add(edit_b = make_button("edit.gif", text("top_edit")));
218 if (can_button("refresh"))
219 top1.add(refresh_b = make_button("refresh.gif", text("top_refresh")));
220 if (!read_only && can_button("info"))
221 top1.add(props_b = make_button("props.gif", text("top_info")));
222 if (acl_support && !read_only && can_button("acl"))
223 top1.add(acl_b = make_button("acl.gif", text("top_eacl")));
224 if (attr_support && !read_only && can_button("attr"))
225 top1.add(attr_b = make_button("attr.gif", text("top_attr")));
226 if (ext_support && !read_only && can_button("ext"))
227 top1.add(ext_b = make_button("ext.gif", text("top_ext")));
228 if (can_button("search"))
229 top1.add(search_b = make_button("search.gif", text("top_search")));
233 Panel top2 = new Panel();
234 top2.setLayout(new GridLayout(1, 0));
235 if (can_button("delete"))
236 top2.add(delete_b = make_button("delete.gif",
237 text("top_delete")));
238 if (can_button("new")) {
239 top2.add(new_b = make_button("new.gif",
241 top2.add(hnew_b = make_button("html.gif",
244 if (can_button("upload"))
245 top2.add(upload_b = make_button("upload.gif",
246 text("top_upload")));
247 top2.add(extract_b = make_button("extract.gif",
248 text("top_extract")));
249 if (can_button("mkdir"))
250 top2.add(mkdir_b = make_button("mkdir.gif",
252 if (getParameter("follow").equals("0") &&
253 can_button("makelink"))
254 top2.add(makelink_b = make_button("makelink.gif",
256 if (can_button("rename"))
257 top2.add(rename_b = make_button("rename.gif",
258 text("top_rename")));
259 if ((sambamode || nfsmode != 0) &&
260 getParameter("sharing").equals("1") &&
261 can_button("sharing"))
262 top2.add(share_b = make_button("share.gif",
264 if (getParameter("mounting").equals("1") &&
266 top2.add(mount_b = make_button("mount.gif",
270 if (can_button("copy")) {
271 Panel top3 = new Panel();
272 top3.setLayout(new GridLayout(1, 0));
273 top3.add(copy_b = make_button("copy.gif",
275 top3.add(cut_b = make_button("cut.gif",
277 top3.add(paste_b = make_button("paste.gif",
283 follow_links = getParameter("follow").equals("1");
285 // create directory tree
286 BorderPanel left = new BorderPanel(2, Util.body);
287 left.setLayout(new BorderLayout());
288 root = new FileNode(new RemoteFile(this, get_text("root.cgi")[0],null));
289 left.add("Center", dirs = new Hierarchy(root, this));
291 root.open = true; root.fill();
293 // create file list window
294 BorderPanel right = new BorderPanel(2, Util.body);
295 right.setLayout(new BorderLayout());
296 Panel rtop = new Panel();
297 rtop.setLayout(new BorderLayout());
298 rtop.add("Center", pathname = new TextField());
299 rtop.add("East", history_b = new CbButton(text("history_button"),this));
300 right.add("North", rtop);
301 pathname.setFont(fixed);
302 String cols[] = { "", text("right_name"), text("right_size"),
303 text("right_user"), text("right_group"),
304 text("right_date") };
305 float widths[] = { .07f, .33f, .15f, .15f, .15f, .15f };
306 right.add("Center", files = new MultiColumn(cols, this));
307 files.setWidths(widths);
308 files.setDrawLines(false);
309 files.setMultiSelect(true);
310 files.setFont(fixed);
311 show_files(root.file);
313 ResizePanel mid = new ResizePanel(left, right, .3, false);
316 // Go to the restricted directory
317 String home = getParameter("home");
318 String go = getParameter("goto");
319 String open = getParameter("open");
321 find_directory(open, true);
323 else if (go != null && go.equals("1")) {
325 find_directory(home, true);
326 else if (!accroot[0].equals("/"))
327 find_directory(accroot[0], true);
331 Font make_font(String name, int defsize)
333 String str = getParameter(name);
334 int size = str == null || str.equals("") ? defsize :
335 Integer.parseInt(str);
336 return new Font("courier", Font.PLAIN, size);
339 // Looks up an applet parameter for a colour, and returns it if
340 // defined, otherwise the default. MUST be in RRGGBB hex format
341 Color get_colour(String name, Color def)
343 String str = getParameter("applet_"+name);
348 return new Color(get_hex(str, 0),
354 int get_hex(String str, int pos)
356 str = str.toUpperCase();
357 char c1 = str.charAt(pos), c2 = str.charAt(pos+1);
358 int b1 = Character.isDigit(c1) ? c1-48 : c1-65+10;
359 int b2 = Character.isDigit(c2) ? c2-48 : c2-65+10;
360 return (b1<<4) + (b2);
363 boolean can_button(String name)
365 return getParameter("no_"+name) == null;
368 CbButton make_button(String f, String t)
371 return new CbButton(get_image(f), this);
373 return new CbButton(get_image(f), t, CbButton.ABOVE, this);
376 // Gets an image from the images directory
377 Image get_image(String img)
379 return getImage(getDocumentBase(), images+"/"+img);
382 // Gets charset parameter from Content-Type: header
383 String get_charset(String ct)
387 StringTokenizer st = new StringTokenizer(ct, ";");
388 while (st.hasMoreTokens()) {
389 String l = st.nextToken().trim();
390 if (l.startsWith("charset=")) {
391 // get the value of charset= param.
392 return l.substring(8);
398 String[] get_text(String url)
401 long now = System.currentTimeMillis();
402 if (url.indexOf('?') > 0) url += "&rand="+now;
403 else url += "?rand="+now;
404 url += "&trust="+trust;
406 URL u = new URL(getDocumentBase(), url);
407 URLConnection uc = u.openConnection();
409 String charset = get_charset(uc.getContentType());
410 InputStream ris = uc.getInputStream();
411 BufferedReader is = null;
412 if (charset == null) {
413 is = new BufferedReader(new InputStreamReader(ris));
416 // Try to use a character set, and handle failure
418 is = new BufferedReader(
419 new InputStreamReader(ris, charset));
423 is = new BufferedReader(
424 new InputStreamReader(ris));
427 Vector lv = new Vector();
429 String l = is.readLine();
430 if (l == null) { break; }
434 String rv[] = new String[lv.size()];
441 String err[] = { e.getClass().getName()+" : "+e.getMessage() };
446 void set_cookie(URLConnection conn)
449 conn.setRequestProperty("Cookie", session);
450 conn.setRequestProperty("Referer", referer);
453 // Fill the multicolumn list with files from some directory
454 boolean show_files(RemoteFile f)
456 RemoteFile fl[] = f.list();
457 if (fl == null) return false;
459 Object rows[][] = new Object[fl.length+1][];
460 long now = System.currentTimeMillis();
462 // Sort listing by chosen column
463 if (f != showing_files) {
464 // Directory has changed .. assume sort by name
465 files.sortingArrow(1, 1);
467 else if (files.sortdir != 0) {
468 // Sort by chosen order
469 RemoteFile fls[] = new RemoteFile[fl.length];
470 System.arraycopy(fl, 0, fls, 0, fl.length);
471 QuickSort.sort(fls, files.sortcol, files.sortdir);
475 // Create parent directory row
476 rows[0] = new Object[6];
477 rows[0][0] = get_image("dir.gif");
479 rows[0][2] = rows[0][3] = rows[0][4] = rows[0][5] = "";
482 Date n = new Date(now);
483 for(int i=0; i<fl.length; i++) {
484 Object row[] = rows[i+1] = new Object[6];
485 if (fl[i].shared() && fl[i].mounted())
486 row[0] = get_image("smdir.gif");
487 else if (fl[i].shared() && fl[i].mountpoint())
488 row[0] = get_image("sudir.gif");
489 else if (fl[i].shared())
490 row[0] = get_image("sdir.gif");
491 else if (fl[i].mounted())
492 row[0] = get_image("mdir.gif");
493 else if (fl[i].mountpoint())
494 row[0] = get_image("udir.gif");
496 row[0] = get_image(RemoteFile.tmap[fl[i].type]);
498 if (fl[i].size < 1000)
499 row[2] = spad(fl[i].size, 5)+" B";
500 else if (fl[i].size < 1000000)
501 row[2] = spad(fl[i].size/1000, 5)+" kB";
503 row[2] = spad(fl[i].size/1000000, 5)+" MB";
505 row[4] = fl[i].group;
506 Date d = new Date(fl[i].modified);
507 //if (now - fl[i].modified < 24*60*60*1000) {
508 if (n.getDate() == d.getDate() &&
509 n.getMonth() == d.getMonth() &&
510 n.getYear() == d.getYear()) {
512 row[5] = pad(d.getHours(),2)+":"+
513 pad(d.getMinutes(),2);
515 //else if (now - fl[i].modified < 24*60*60*365*1000) {
516 else if (n.getYear() == d.getYear()) {
518 row[5] = pad(d.getDate(),2)+"/"+
519 monmap[d.getMonth()];
523 row[5] = monmap[d.getMonth()]+"/"+
524 pad(d.getYear()%100, 2);
527 files.addItems(rows);
530 pathname.setText(f.path);
534 String pad(int n, int s)
536 String rv = String.valueOf(n);
537 while(rv.length() < s)
542 String spad(long n, int s)
544 String rv = String.valueOf(n);
545 while(rv.length() < s)
550 String trim_path(String p)
552 while(p.endsWith("/"))
553 p = p.substring(0, p.length()-1);
558 // Called when a node with children is opened
559 public void openNode(Hierarchy h, HierarchyNode n)
561 FileNode fn = (FileNode)n;
566 // Called when a node is closed
567 public void closeNode(Hierarchy h, HierarchyNode n)
572 // Called when the user clicks on a node
573 public void clickNode(Hierarchy h, HierarchyNode n)
575 FileNode fn = (FileNode)n;
576 if (showing_files != fn.file)
581 // Called when a user double-clicks on a node
582 public void doubleNode(Hierarchy h, HierarchyNode n)
586 // Called when a button is clicked
587 public void click(CbButton b)
589 int s = files.selected();
590 int ss[] = files.allSelected();
591 RemoteFile f = null, ff[] = new RemoteFile[0];
592 if (s > 0 || s == 0 && ss.length > 1) {
593 // At least one non-.. file was selected
594 boolean parentsel = false;
595 for(int i=0; i<ss.length; i++)
598 RemoteFile list[] = showing_list;
600 // need to exclude .. from selected list!
601 ff = new RemoteFile[ss.length-1];
602 for(int i=0,j=0; i<ss.length; i++)
604 ff[j++] = list[ss[i]-1];
605 f = s == 0 ? ff[0] : list[s-1];
608 // include all selected files
610 ff = new RemoteFile[ss.length];
611 for(int i=0; i<ss.length; i++)
612 ff[i] = list[ss[i]-1];
615 FileNode d = (FileNode)dirs.selected();
617 // Return to the webmin index
619 URL u = new URL(getDocumentBase(),
620 getParameter("return"));
621 getAppletContext().showDocument(u);
623 catch(Exception e) { }
625 else if (b == config_b) {
626 // Open the module config window
628 URL u = new URL(getDocumentBase(),
629 getParameter("config"));
630 getAppletContext().showDocument(u, "_self");
632 catch(Exception e) { }
634 else if (b == edit_b) {
635 // Open a window for editing the selected file
637 new ErrorWindow(text("top_efile"));
638 else if (f.type == 0 || f.type > 4)
639 new ErrorWindow(text("edit_enormal"));
640 else if (is_html_filename(f.path) && !force_text) {
643 JSObject win = JSObject.getWindow(this);
644 String params[] = { f.path, "" };
645 win.call("htmledit", params);
648 new ErrorWindow(text("html_efailed",
654 new EditorWindow(f, this);
657 else if (b == down_b) {
658 // Force download of the selected file
659 if (f == null) return;
662 else if (b == preview_b) {
663 // Open preview window for selected file
664 if (f == null) return;
665 if (f.type == RemoteFile.DIR)
666 new ErrorWindow(text("preview_eimage"));
668 new PreviewWindow(this, f);
670 else if (b == refresh_b) {
671 // Refesh the selected directory (and thus any subdirs)
672 if (d == null) return;
676 else if (b == props_b) {
677 // Display the properties window
678 if (f == null) return;
679 new PropertiesWindow(f, this);
681 else if (b == acl_b) {
682 // Display the ACL window (if filesystem supports them)
683 if (f == null) return;
684 FileSystem filefs = find_filesys(f);
685 if (filefs == null) return;
687 new ACLWindow(this, f);
689 new ErrorWindow(text("eacl_efs", filefs.mount));
691 else if (b == attr_b) {
692 // Display the attributes window (if filesystem supports them)
693 if (f == null) return;
694 FileSystem filefs = find_filesys(f);
695 if (filefs == null) return;
697 new AttributesWindow(this, f);
699 new ErrorWindow(text("attr_efs", filefs.mount));
701 else if (b == ext_b) {
702 // Display EXT attributes window (if filesystem supports them)
703 if (f == null) return;
704 FileSystem filefs = find_filesys(f);
705 if (filefs == null) return;
707 new EXTWindow(this, f);
709 new ErrorWindow(text("ext_efs", filefs.mount));
711 else if (b == copy_b) {
712 // Copy the selected files
713 if (f == null) return;
717 else if (b == cut_b) {
718 // Cut the selected file
719 if (f == null) return;
723 else if (b == paste_b) {
724 // Paste the copied file
725 if (cut_buffer == null) {
726 new ErrorWindow(text("paste_ecopy"));
730 // Check for existing file clashes
733 // Go through all the files to paste
734 for(int i=0; i<cut_buffer.length; i++) {
735 RemoteFile cf = cut_buffer[i];
737 // Check for an existing file
738 RemoteFile already = showing_files.find(cf.name);
739 String sp = showing_files.path;
740 String dest_path = sp.equals("/") ? sp+cf.name
742 if (already != null) {
743 // File exists .. offer to rename
744 new OverwriteWindow(this, already, cf, i);
747 // do the move or copy
748 RemoteFile nf = paste_file(cf, showing_files,
749 dest_path, null, cut_mode);
750 if (cut_mode && nf != null) {
751 // Paste from the destination path
759 else if (b == delete_b) {
760 // Delete the selected files
761 if (f == null) return;
762 new DeleteWindow(this, ff);
764 else if (b == new_b) {
765 // Open a window for creating a text file
766 new EditorWindow(showing_files.path, this);
768 else if (b == hnew_b) {
769 // Open a window for creating an HTML file
771 JSObject win = JSObject.getWindow(this);
772 String params[] = { "", showing_files.path };
773 win.call("htmledit", params);
776 new ErrorWindow(text("html_efailed",
780 else if (b == upload_b) {
781 // Call javascript to open an upload window
783 JSObject win = JSObject.getWindow(this);
784 String params[] = { showing_files.path };
785 win.call("upload", params);
788 new ErrorWindow(text("upload_efailed", e.getMessage()));
791 else if (b == extract_b) {
792 // Ask for confirmation, then extract file
793 if (f == null) return;
794 if (f.type == 0 || f.type == 6 || f.type == 7)
795 new ErrorWindow(text("extract_etype", f.path));
797 new ExtractWindow(this, f);
799 else if (b == mkdir_b) {
800 // Prompt for new directory
801 new MkdirWindow(showing_files.path, this);
803 else if (b == makelink_b) {
804 // Prompt for a new symlink
805 new LinkWindow(showing_files.path, this);
807 else if (b == rename_b) {
808 // Prompt for new filename
809 if (f == null) return;
810 new RenameWindow(this, f);
812 else if (b == share_b) {
813 // Open a window for editing sharing options
814 if (f == null || f.type != RemoteFile.DIR) return;
815 new SharingWindow(f, this);
817 else if (b == mount_b) {
818 // Check if the selected directory is a mount point
819 if (f == null || f.type != RemoteFile.DIR) return;
820 FileSystem fs = f.fs();
822 new ErrorWindow(text("mount_epoint", f.path));
824 new MountWindow(this, fs, f);
826 else if (b == search_b) {
827 // Open window for finding a file
828 new SearchWindow(showing_files.path, this);
830 else if (b == history_b) {
831 // Open entered file history window
832 if (history_list.size() > 0) {
833 new HistoryWindow(this);
838 boolean is_html_filename(String path)
840 for(int i=0; i<htmlexts.length; i++)
841 if (path.toLowerCase().endsWith(htmlexts[i]))
846 boolean under_root_dir(String p, String roots[])
850 for(int r=0; r<roots.length; r++) {
851 int rl = roots[r].length();
852 if (roots[r].equals("/"))
854 else if (l >= rl && p.substring(0, rl).equals(roots[r]))
856 else if (l < rl && roots[r].substring(0, l).equals(p))
862 // Download some file to the user's browser, if possible
863 void download_file(RemoteFile f)
865 if (f.type == RemoteFile.DIR && !archive.equals("0"))
866 new DownloadDirWindow(this, f);
867 else if (f.type == RemoteFile.DIR || f.type > 4)
868 new ErrorWindow(text("view_enormal2"));
870 open_file_window(f, true, 0);
873 // Returns the object for some directory, or null if not found.
874 RemoteFile find_directory(String p, boolean fill)
876 boolean can = under_root_dir(p, accroot) &&
877 !under_root_dir(p, accnoroot);
879 new ErrorWindow(text("find_eaccess", p));
882 FileNode posnode = root;
883 RemoteFile pos = posnode.file;
884 StringTokenizer tok = new StringTokenizer(p, "/");
885 while(tok.hasMoreTokens()) {
886 String fn = tok.nextToken();
887 if (fn.equals("")) continue;
888 RemoteFile fl[] = pos.list();
889 if (fl == null) return null;
894 boolean found = false;
895 for(int i=0; i<fl.length; i++)
896 if (fl[i].name.equals(fn)) {
901 new ErrorWindow(text("find_eexist", fn, p));
905 new ErrorWindow(text("find_edir", fn, p));
909 posnode = (FileNode)nodemap.get(pos);
912 if (show_files(pos)) {
915 dirs.select(posnode);
922 FileSystem find_filesys(RemoteFile f)
924 FileSystem filefs = null;
925 for(int i=0; i<fslist.size(); i++) {
926 FileSystem fs = (FileSystem)fslist.elementAt(i);
927 int l = fs.mount.length();
928 if (fs.mount.equals(f.path) ||
929 (f.path.length() >= l+1 &&
930 f.path.substring(0, l+1).equals(fs.mount+"/")) ||
931 fs.mount.equals("/")) {
938 public boolean action(Event e, Object o)
940 if (e.target == pathname) {
941 // A new path was entered.. cd to it
942 String p = pathname.getText().trim();
943 if (p.equals("")) return true;
944 find_directory(p, true);
946 // Add to the history
947 if (!history_list.contains(p)) {
948 history_list.insertElementAt(p, 0);
956 // Called on a single click on a list item
957 public void singleClick(MultiColumn list, int num)
962 // Called upon double-clicking on a list item
963 public void doubleClick(MultiColumn list, int num)
966 // Go to parent directory
967 if (showing_files.directory != null) {
968 ((FileNode)nodemap.get(showing_files)).open = false;
969 show_files(showing_files.directory);
970 dirs.select((FileNode)nodemap.get(showing_files));
975 RemoteFile d = showing_list[num-1];
977 // Open this directory
978 FileNode pn = (FileNode)nodemap.get(showing_files);
981 FileNode fn = (FileNode)nodemap.get(d);
989 else if (d.type <= 4) {
990 // Direct the browser to this file
991 open_file_window(d, list.last_event.shiftDown(), 0);
995 // Called when the user clicks on a column heading so that it can
997 public void headingClicked(MultiColumn list, int col)
1000 return; // ignore click on icon column?
1001 if (col == list.sortcol) {
1002 list.sortingArrow(col, list.sortdir == 2 ? 1 : 2);
1005 list.sortingArrow(col, 1);
1008 // Re-show the list in the new order, but with the same files selected
1009 int ss[] = files.allSelected();
1010 RemoteFile ssf[] = new RemoteFile[ss.length];
1011 for(int i=0; i<ss.length; i++)
1012 ssf[i] = showing_list[ss[i]-1];
1013 show_files(showing_files);
1014 for(int i=0; i<ss.length; i++) {
1015 for(int j=0; j<showing_list.length; j++) {
1016 if (showing_list[j] == ssf[i]) {
1025 void open_file_window(RemoteFile f, boolean download, int format)
1028 String ext = format == 1 ? ".zip" :
1029 format == 2 ? ".tgz" :
1030 format == 3 ? ".tar" : "";
1033 urlstr = "show.cgi"+urlize(f.path)+ext+
1034 "?rand="+System.currentTimeMillis()+
1035 "&type=application%2Funknown"+
1041 urlstr = "show.cgi"+urlize(f.path)+ext+
1042 "?rand="+System.currentTimeMillis()+
1049 String l[] = get_text(urlstr+"&test=1");
1050 if (l[0].length() > 0) {
1051 new ErrorWindow(text("eopen", l[0]));
1057 getAppletContext().showDocument(
1058 new URL(getDocumentBase(), urlstr));
1061 getAppletContext().showDocument(
1062 new URL(getDocumentBase(), urlstr), "show");
1065 catch(Exception e) { }
1068 static String urlize(String s)
1070 StringBuffer rv = new StringBuffer();
1071 for(int i=0; i<s.length(); i++) {
1072 char c = s.charAt(i);
1074 rv.append("%0"+Integer.toString(c, 16));
1075 else if ((!Character.isLetterOrDigit(c) && c != '/' &&
1076 c != '.' && c != '_' && c != '-') || c >= 128)
1077 rv.append("%"+Integer.toString(c, 16));
1081 return rv.toString();
1084 static String un_urlize(String s)
1086 StringBuffer rv = new StringBuffer();
1087 for(int i=0; i<s.length(); i++) {
1088 char c = s.charAt(i);
1090 rv.append((char)Integer.parseInt(
1091 s.substring(i+1, i+3), 16));
1097 return rv.toString();
1100 // Called back by Javascript when a file or directory has been modified
1101 public void upload_notify(String path_str, String info)
1103 int sl = path_str.lastIndexOf('/');
1104 String par_str = path_str.substring(0, sl),
1105 file_str = path_str.substring(sl+1);
1106 RemoteFile par = find_directory(par_str, false);
1107 RemoteFile upfile = par.find(file_str);
1109 if (upfile == null) {
1110 // Need to add this file/directory
1111 upfile = new RemoteFile(this, info, par);
1114 else if (upfile.type == RemoteFile.DIR) {
1115 // Is a directory .. refresh from server
1116 FileNode upnode = (FileNode)nodemap.get(upfile);
1120 show_files(showing_files);
1122 catch(Exception e) {
1123 // In some cases, any attempt to make an HTTP request to
1124 // refresh the directory may fail because Java apparently has
1125 // some security rules that limit what a function called from
1126 // JavaScript is allowed to do. All we can do is ignore the
1128 e.printStackTrace();
1132 // Called back by Javascript to show an upload-related error
1133 public void upload_error(String err)
1135 new ErrorWindow(err);
1138 public String text(String k, String p[])
1140 String rv = (String)lang.get(k);
1141 if (rv == null) rv = "???";
1142 for(int i=0; i<p.length; i++) {
1143 int idx = rv.indexOf("$"+(i+1));
1145 rv = rv.substring(0, idx)+p[i]+rv.substring(idx+2);
1150 public String text(String k)
1156 public String text(String k, String p1)
1158 String p[] = { p1 };
1162 public String text(String k, String p1, String p2)
1164 String p[] = { p1, p2 };
1168 RemoteFile paste_file(RemoteFile src, RemoteFile dir,
1169 String dest, RemoteFile already, boolean mode)
1171 // Move or copy the actual file
1172 String[] rv = get_text((mode ? "move.cgi" : "copy.cgi")+
1173 "?from="+urlize(src.path)+
1174 "&to="+urlize(dest));
1175 if (rv[0].length() > 0) {
1176 new ErrorWindow(text(
1177 mode ? "paste_emfailed" : "paste_ecfailed", rv[0]));
1180 RemoteFile file = new RemoteFile(this, rv[1], dir);
1181 if (already == null) {
1182 // Add to the parent directory
1186 // Update the existing file
1187 already.type = file.type;
1188 already.user = file.user;
1189 already.group = file.group;
1190 already.size = file.size;
1191 already.perms = file.perms;
1192 already.modified = file.modified;
1196 // Delete the old file
1197 src.directory.delete(src);
1199 if (src.type == 0) {
1200 // Moving or copying a directory.. update the tree
1201 FileNode dest_par_node =
1202 (FileNode)nodemap.get(showing_files);
1203 dest_par_node.add(new FileNode(file));
1205 FileNode cut_par_node =
1206 (FileNode)nodemap.get(src.directory);
1207 FileNode cut_file_node =
1208 (FileNode)nodemap.get(src);
1209 if (cut_par_node != null &&
1210 cut_file_node != null)
1211 cut_par_node.ch.removeElement(
1216 show_files(showing_files);
1220 // Loads the list of filesystems from the server, and refreshes all
1222 void get_filesystems()
1224 String f[] = get_text("filesystems.cgi");
1225 got_filesystems = f[0].equals("1");
1226 acl_support = false;
1227 attr_support = false;
1228 ext_support = false;
1230 fslist.removeAllElements();
1231 if (got_filesystems) {
1232 for(int i=1; i<f.length; i++) {
1233 FileSystem fs = new FileSystem(f[i]);
1234 fslist.addElement(fs);
1235 if (fs.acls) acl_support = true;
1236 if (fs.attrs) attr_support = true;
1237 if (fs.ext) ext_support = true;
1238 mounts.put(fs.mount, fs);
1243 String join_array(String l[])
1246 for(int i=0; i<l.length; i++)
1251 static String replace_str(String str, String os, String ns)
1257 while((idx = rv.indexOf(os, pos)) >= 0) {
1258 rv = rv.substring(0, idx)+
1259 ns+rv.substring(idx+os.length());
1260 pos = idx+ns.length()+1;
1266 // A node in the directory tree
1267 class FileNode extends HierarchyNode
1273 FileNode(RemoteFile file)
1276 parent = file.parent;
1280 parent.nodemap.put(file, this);
1283 // Create the nodes for subdirectories
1287 RemoteFile l[] = file.list();
1288 if (l == null) return;
1289 ch.removeAllElements();
1290 for(int i=0; i<l.length; i++)
1292 ch.addElement(new FileNode(l[i]));
1293 parent.dirs.redraw();
1298 void add(FileNode n)
1300 for(int i=0; i<=ch.size(); i++) {
1301 FileNode ni = i==ch.size() ? null : (FileNode)ch.elementAt(i);
1302 if (ni == null || ni.text.compareTo(n.text) > 0) {
1303 ch.insertElementAt(n, i);
1311 im = parent.get_image(file.shared() && file.mounted() ? "smdir.gif" :
1312 file.shared() && file.mountpoint() ? "sudir.gif" :
1313 file.shared() ? "sdir.gif" :
1314 file.mounted() ? "mdir.gif" :
1315 file.mountpoint() ? "udir.gif" :
1319 // Forces a re-load from the server
1330 static final int DIR = 0;
1331 static final int TEXT = 1;
1332 static final int IMAGE = 2;
1333 static final int BINARY = 3;
1334 static final int UNKNOWN = 4;
1335 static final int SYMLINK = 5;
1336 static final int DEVICE = 6;
1337 static final int PIPE = 7;
1338 static final String[] tmap = { "dir.gif", "text.gif", "image.gif",
1339 "binary.gif", "unknown.gif",
1340 "symlink.gif", "device.gif",
1352 RemoteFile directory;
1354 // Parse a line of text to a file object
1355 RemoteFile(FileManager parent, String line, RemoteFile d)
1357 this.parent = parent;
1358 StringTokenizer tok = new StringTokenizer(line, "\t");
1359 if (tok.countTokens() < 7) {
1360 String err = "Invalid file line : "+line;
1361 new ErrorWindow(err);
1362 throw new Error(err);
1364 path = tok.nextToken();
1365 path = parent.replace_str(path, "\\t", "\t");
1366 path = parent.replace_str(path, "\\\\", "\\");
1367 type = Integer.parseInt(tok.nextToken());
1368 user = tok.nextToken();
1369 group = tok.nextToken();
1370 size = Long.parseLong(tok.nextToken());
1371 perms = Integer.parseInt(tok.nextToken());
1372 modified = Long.parseLong(tok.nextToken())*1000;
1373 if (type == 5) linkto = tok.nextToken();
1375 if (path.equals("/")) name = "/";
1376 else name = path.substring(path.lastIndexOf('/')+1);
1379 // Create a new, empty file object
1382 // Returns a list of files in this directory
1386 String l[] = parent.get_text("list.cgi?dir="+
1387 parent.urlize(path));
1388 if (l[0].length() > 0) {
1389 //list = new RemoteFile[0];
1390 // Error reading the remote directory!
1391 new ErrorWindow(parent.text("list_edir", path, l[0]));
1395 list = new RemoteFile[l.length-3];
1396 for(int i=3; i<l.length; i++)
1397 list[i-3] = new RemoteFile(parent, l[i], this);
1403 RemoteFile find(String n)
1405 RemoteFile l[] = list();
1407 for(int i=0; i<l.length; i++)
1408 if (l[i].name.equals(n))
1414 void add(RemoteFile f)
1416 RemoteFile nlist[] = new RemoteFile[list.length+1];
1418 for(int i=0; i<list.length; i++) {
1419 if (list[i].name.compareTo(f.name) > 0 && offset == 0) {
1423 nlist[i+offset] = list[i];
1425 if (offset == 0) nlist[list.length] = f;
1429 void delete(RemoteFile f)
1431 RemoteFile nlist[] = new RemoteFile[list.length-1];
1432 for(int i=0,j=0; i<list.length; i++)
1434 nlist[j++] = list[i];
1440 return type == DIR &&
1441 (parent.stab.get(path) != null ||
1442 parent.ntab.get(path) != null);
1445 boolean mountpoint()
1447 return type == DIR && fs() != null;
1452 FileSystem fs = fs();
1453 return type == DIR && fs != null && fs.mtab;
1458 return (FileSystem)parent.mounts.get(path);
1463 class EditorWindow extends FixedFrame implements CbButtonCallback
1467 CbButton save_b, saveclose_b, cancel_b, goto_b, find_b;
1470 FileManager filemgr;
1471 GotoWindow goto_window;
1472 FindReplaceWindow find_window;
1474 // Editing an existing file
1475 EditorWindow(RemoteFile f, FileManager p)
1478 file = f; filemgr = p;
1480 setTitle(filemgr.text("edit_title", file.path));
1484 URL u = new URL(filemgr.getDocumentBase(),
1485 "show.cgi"+filemgr.urlize(file.path)+
1486 "?rand="+System.currentTimeMillis()+
1487 "&trust="+filemgr.trust+"&edit=1"+
1489 URLConnection uc = u.openConnection();
1490 filemgr.set_cookie(uc);
1491 int len = uc.getContentLength();
1492 InputStream is = uc.getInputStream();
1496 buf = new byte[uc.getContentLength()];
1498 while(got < buf.length)
1499 got += is.read(buf, got, buf.length-got);
1502 // Length is unknown .. read till the end
1505 byte data[] = new byte[16384];
1507 try { got = is.read(data); }
1508 catch(EOFException ex) { break; }
1509 if (got <= 0) break;
1510 byte nbuf[] = new byte[buf.length + got];
1511 System.arraycopy(buf, 0, nbuf, 0, buf.length);
1512 System.arraycopy(data, 0, nbuf, buf.length, got);
1516 String s = new String(buf, 0);
1517 if (s.indexOf("\r\n") != -1) {
1518 dosmode.setState(true);
1519 s = FileManager.replace_str(s, "\r\n", "\n");
1523 file.size = buf.length;
1525 catch(Exception e) { e.printStackTrace(); }
1528 // Creating a new file
1529 EditorWindow(String f, FileManager p)
1534 setTitle(filemgr.text("edit_title2"));
1535 name.setText(f.equals("/") ? f : f+"/");
1536 name.select(name.getText().length(), name.getText().length());
1539 void makeUI(boolean add_name)
1541 setLayout(new BorderLayout());
1543 Panel np = new Panel();
1544 np.setLayout(new BorderLayout());
1545 np.add("West", new Label(filemgr.text("edit_filename")));
1546 np.add("Center", name = new TextField());
1547 name.setFont(filemgr.fixed);
1550 add("Center", edit = new TextArea(20, 80));
1551 edit.setFont(filemgr.fixed);
1552 Panel bot = new Panel();
1553 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1554 bot.add(dosmode = new Checkbox("Windows newlines"));
1555 bot.add(goto_b = new CbButton(filemgr.get_image("goto.gif"),
1556 filemgr.text("edit_goto"),
1557 CbButton.LEFT, this));
1558 bot.add(find_b = new CbButton(filemgr.get_image("find.gif"),
1559 filemgr.text("edit_find"),
1560 CbButton.LEFT, this));
1561 bot.add(new Label(" "));
1562 bot.add(save_b = new CbButton(filemgr.get_image("save.gif"),
1563 filemgr.text("save"),
1564 CbButton.LEFT, this));
1565 bot.add(saveclose_b = new CbButton(filemgr.get_image("save.gif"),
1566 filemgr.text("edit_saveclose"),
1567 CbButton.LEFT, this));
1568 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1569 filemgr.text("close"),
1570 CbButton.LEFT, this));
1572 Util.recursiveBody(this);
1577 public void click(CbButton b)
1579 if (b == save_b || b == saveclose_b) {
1580 RemoteFile par = null, already = null;
1583 // Locate the filemgr directory
1584 save_path = filemgr.trim_path(name.getText());
1585 int sl = save_path.lastIndexOf('/');
1586 par = filemgr.find_directory(
1587 save_path.substring(0, sl), false);
1588 if (par == null) return;
1589 already = par.find(save_path.substring(sl+1));
1590 if (already != null &&
1591 (already.type == 0 || already.type == 5)) {
1593 filemgr.text("edit_eover", save_path));
1597 else save_path = file.path;
1599 // Save the file back again
1600 String s = edit.getText(), line;
1601 s = FileManager.replace_str(s, "\r\n", "\n");
1603 if (dosmode.getState()) {
1604 // Convert to DOS newlines
1605 s = FileManager.replace_str(s, "\n", "\r\n");
1608 // Remove any DOS newlines
1609 s = FileManager.replace_str(s, "\r\n", "\n");
1611 URL u = new URL(filemgr.getDocumentBase(),
1612 "save.cgi"+filemgr.urlize(save_path)+
1613 "?rand="+System.currentTimeMillis()+
1614 "&trust="+filemgr.trust+
1615 "&length="+s.length()+
1617 URLConnection uc = u.openConnection();
1618 uc.setRequestProperty("Content-type", "text/plain");
1619 filemgr.set_cookie(uc);
1620 uc.setDoOutput(true);
1621 OutputStream os = uc.getOutputStream();
1622 byte buf[] = new byte[s.length()];
1623 s.getBytes(0, buf.length, buf, 0);
1627 new BufferedReader(new InputStreamReader(
1628 uc.getInputStream()));
1629 String err = is.readLine();
1630 if (err.length() > 0) {
1632 filemgr.text("edit_esave", err));
1636 line = is.readLine();
1639 catch(Exception e) { e.printStackTrace(); return; }
1642 // Create and insert or replace the file object
1643 file = new RemoteFile(filemgr, line, par);
1644 if (already != null) {
1645 // A file with this name exists
1646 already.type = file.type;
1647 already.user = file.user;
1648 already.group = file.group;
1649 already.size = file.size;
1650 already.perms = file.perms;
1651 already.modified = file.modified;
1659 file.size = s.length();
1660 file.modified = System.currentTimeMillis();
1662 filemgr.show_files(filemgr.showing_files);
1663 if (b == saveclose_b)
1666 else if (b == cancel_b) {
1670 else if (b == goto_b) {
1671 // Open a dialog asking which line to go to
1672 if (goto_window != null)
1673 goto_window.toFront();
1675 goto_window = new GotoWindow(this);
1677 else if (b == find_b) {
1678 // Open the search (and replace) dialog
1679 if (find_window != null)
1680 find_window.toFront();
1682 find_window = new FindReplaceWindow(this);
1686 public void dispose()
1689 if (goto_window != null) goto_window.dispose();
1690 if (find_window != null) find_window.dispose();
1694 class GotoWindow extends FixedFrame implements CbButtonCallback
1696 EditorWindow editor;
1697 FileManager filemgr;
1699 CbButton goto_b, cancel_b;
1701 GotoWindow(EditorWindow e)
1704 filemgr = e.filemgr;
1706 setLayout(new BorderLayout());
1707 add("West", new Label(filemgr.text("edit_gotoline")));
1708 add("Center", line = new TextField(10));
1709 line.setFont(filemgr.fixed);
1710 Panel bot = new Panel();
1711 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1712 bot.add(goto_b = new CbButton(filemgr.get_image("goto.gif"),
1713 filemgr.text("edit_goto"),
1714 CbButton.LEFT, this));
1715 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1716 filemgr.text("close"),
1717 CbButton.LEFT, this));
1719 Util.recursiveBody(this);
1724 public void click(CbButton b)
1727 // Go to the chose line, if it exists
1729 try { lnum = Integer.parseInt(line.getText()); }
1730 catch(Exception e) { return; }
1732 String txt = editor.edit.getText();
1734 for(c=0; c<txt.length(); c++) {
1735 if (txt.charAt(c) == '\n') {
1739 editor.edit.select(c, c);
1741 editor.edit.requestFocus();
1747 else if (b == cancel_b) {
1748 // Just close the window
1753 public void dispose()
1756 editor.goto_window = null;
1759 public boolean handleEvent(Event e)
1761 if (e.target == line && e.id == Event.KEY_RELEASE && e.key == 10) {
1769 class FindReplaceWindow extends FixedFrame implements CbButtonCallback
1771 EditorWindow editor;
1772 FileManager filemgr;
1773 TextField find, replace;
1774 CbButton find_b, replace_b, all_b, cancel_b;
1776 FindReplaceWindow(EditorWindow e)
1779 filemgr = e.filemgr;
1780 setLayout(new BorderLayout());
1782 Panel left = new Panel();
1783 left.setLayout(new GridLayout(2, 1));
1784 left.add(new Label(filemgr.text("edit_searchfor")));
1785 left.add(new Label(filemgr.text("edit_replaceby")));
1788 Panel right = new Panel();
1789 right.setLayout(new GridLayout(2, 1));
1790 right.add(find = new TextField(40));
1791 find.setFont(filemgr.fixed);
1792 right.add(replace = new TextField(40));
1793 replace.setFont(filemgr.fixed);
1794 add("Center", right);
1796 Panel bot = new Panel();
1797 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1798 bot.add(find_b = new CbButton(filemgr.get_image("find.gif"),
1799 filemgr.text("edit_find"),
1800 CbButton.LEFT, this));
1801 bot.add(replace_b = new CbButton(filemgr.get_image("replace.gif"),
1802 filemgr.text("edit_replace"),
1803 CbButton.LEFT, this));
1804 bot.add(all_b = new CbButton(filemgr.get_image("all.gif"),
1805 filemgr.text("edit_all"),
1806 CbButton.LEFT, this));
1807 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1808 filemgr.text("close"),
1809 CbButton.LEFT, this));
1811 Util.recursiveBody(this);
1816 public void click(CbButton b)
1818 String findtxt = find.getText();
1819 String edittxt = editor.edit.getText();
1820 if (findtxt.length() == 0)
1823 // Find the next occurrance of the text, starting from
1824 // the cursor + 1, and select it
1825 int pos = edittxt.indexOf(findtxt,
1826 editor.edit.getSelectionStart()+1);
1828 // Not found .. but try wrap-around
1829 pos = edittxt.indexOf(findtxt, 0);
1832 new ErrorWindow(filemgr.text("edit_notfound", findtxt));
1834 editor.edit.select(pos, pos+findtxt.length());
1835 editor.edit.requestFocus();
1838 else if (b == replace_b) {
1839 // If the word to search for is selected, replace it. Otherwise
1840 // just search for the next one
1841 int st = editor.edit.getSelectionStart(),
1842 en = editor.edit.getSelectionEnd();
1844 String sel = edittxt.substring(st, en);
1845 if (sel.equals(findtxt)) {
1846 // Replace the selected
1847 editor.edit.setText(edittxt.substring(0, st)+
1849 edittxt.substring(en));
1850 editor.edit.select(st, st);
1856 else if (b == all_b) {
1857 // Replace all occurrances of the text in the editor
1859 int len = findtxt.length();
1860 int st = editor.edit.getSelectionStart(),
1861 en = editor.edit.getSelectionEnd();
1862 while((pos = edittxt.indexOf(findtxt, pos)) != -1) {
1863 edittxt = edittxt.substring(0, pos)+
1865 edittxt.substring(pos+len);
1868 editor.edit.setText(edittxt);
1869 editor.edit.select(st, en); // put back old selection
1871 else if (b == cancel_b) {
1872 // Just close the window
1877 public void dispose()
1880 editor.find_window = null;
1884 class PropertiesWindow extends FixedFrame implements CbButtonCallback
1887 FileManager filemgr;
1888 CbButton save_b, cancel_b, size_b;
1891 TextField user, group;
1892 Checkbox setuid, setgid;
1893 PermissionsPanel user_p, group_p, other_p;
1898 TextField bytes, files, dirs;
1900 PropertiesWindow(RemoteFile f, FileManager p)
1907 setLayout(new BorderLayout());
1908 Panel bot = new Panel();
1909 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1910 if (file.type == 0) {
1911 bot.add(size_b = new CbButton(filemgr.get_image("refresh.gif"),
1912 filemgr.text("info_getsize"),
1913 CbButton.LEFT, this));
1915 if (filemgr.can_perms || filemgr.can_users) {
1916 bot.add(save_b = new CbButton(filemgr.get_image("save.gif"),
1917 filemgr.text("save"),
1918 CbButton.LEFT, this));
1920 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1921 filemgr.text("cancel"),
1922 CbButton.LEFT, this));
1925 Panel mid = new Panel();
1926 mid.setLayout(new BorderLayout());
1927 TabbedPanel tab = null;
1930 // Create file details section
1931 Panel det = new LinedPanel(filemgr.text("info_file")),
1932 dl = new Panel(), dr = new Panel();
1933 setup_leftright(det, dl, dr);
1934 add_item(filemgr.text("info_path"),
1935 new Label(file.path), dl, dr);
1936 add_item(filemgr.text("info_type"),
1937 new Label(filemgr.text("file_type"+file.type)), dl, dr);
1938 add_item(filemgr.text("info_size"),
1939 new Label(String.valueOf(file.size)),dl,dr);
1940 add_item(filemgr.text("info_mod"),
1941 new Label(String.valueOf(new Date(file.modified))), dl, dr);
1942 if (file.type == 5) {
1943 add_item(filemgr.text("info_link"),
1944 linkto = new TextField(file.linkto, 30), dl, dr);
1945 linkto.setFont(filemgr.fixed);
1947 mid = add_panel(mid, det);
1949 if (filemgr.can_perms) {
1950 // Create permissions section
1951 Panel per = new LinedPanel(filemgr.text("info_perms")),
1952 pl = new Panel(), pr = new Panel();
1953 setup_leftright(per, pl, pr);
1954 add_item(filemgr.text("info_user"),
1955 user_p = new PermissionsPanel(file, 64, filemgr), pl, pr);
1956 add_item(filemgr.text("info_group"),
1957 group_p = new PermissionsPanel(file, 8, filemgr), pl, pr);
1958 add_item(filemgr.text("info_other"),
1959 other_p = new PermissionsPanel(file, 1, filemgr), pl,pr);
1960 if (file.type == 0) {
1961 add_item(filemgr.text("info_sticky"),
1962 sticky = new Checkbox(filemgr.text("info_sticky2")),
1964 sticky.setState((file.perms&01000) != 0);
1966 add_item(filemgr.text("info_octal"),
1967 octal = new TextField(4), pl, pr);
1968 octal.setFont(filemgr.fixed);
1969 octal.setEditable(false);
1970 mid = add_panel(mid, per);
1973 if (filemgr.can_users) {
1974 // Create ownership section
1975 Panel own = new LinedPanel(filemgr.text("info_own")),
1976 ol = new Panel(), or = new Panel();
1977 setup_leftright(own, ol, or);
1978 add_item(filemgr.text("info_user"),
1979 user = new TextField(file.user, 10), ol, or);
1980 user.setFont(filemgr.fixed);
1981 if (file.type != 0) {
1982 add_item(filemgr.text("info_setuid"),
1983 setuid = new Checkbox(filemgr.text("info_setuid2")),
1985 setuid.setState((file.perms & 0x800) != 0);
1987 add_item(filemgr.text("info_group"),
1988 group = new TextField(file.group, 10), ol, or);
1989 group.setFont(filemgr.fixed);
1991 add_item(filemgr.text("info_setgid"),
1992 setgid = new Checkbox(filemgr.text("info_setgid2")),
1995 add_item(filemgr.text("info_setgid"),
1996 setgid = new Checkbox(filemgr.text("info_setgid3")),
1998 setgid.setState((file.perms & 0x400) != 0);
1999 mid = add_panel(mid, own);
2002 if (file.type == 0) {
2003 // Create directory size section, initially empty
2004 Panel szp = new LinedPanel(filemgr.text("info_sizeheader")),
2005 sl = new Panel(), sr = new Panel();
2006 setup_leftright(szp, sl, sr);
2007 add_item(filemgr.text("info_bytes"),
2008 bytes = new TextField("", 10), sl, sr);
2009 bytes.setFont(filemgr.fixed);
2010 bytes.setEditable(false);
2011 add_item(filemgr.text("info_files"),
2012 files = new TextField("", 10), sl, sr);
2013 files.setFont(filemgr.fixed);
2014 files.setEditable(false);
2015 add_item(filemgr.text("info_dirs"),
2016 dirs = new TextField("", 10), sl, sr);
2017 dirs.setFont(filemgr.fixed);
2018 dirs.setEditable(false);
2019 mid = add_panel(mid, szp);
2022 if (file.type == 0 && (filemgr.can_perms || filemgr.can_users)) {
2023 // Create recursion section
2024 Panel rec = new LinedPanel(filemgr.text("info_apply"));
2025 rec.setLayout(new BorderLayout());
2026 rec_mode = new Choice();
2027 for(int i=1; i<=3; i++)
2028 rec_mode.addItem(filemgr.text("info_apply"+i));
2029 rec.add("Center", rec_mode);
2030 mid = add_panel(mid, rec);
2034 Util.recursiveBody(this);
2039 Panel add_panel(Panel p, Component c)
2042 Panel np = new Panel();
2043 np.setLayout(new BorderLayout());
2044 p.add("Center", np);
2048 public void click(CbButton b)
2052 int perms = get_perms();
2053 String user_str = user != null ? user.getText() : null;
2054 String group_str = group != null ? group.getText() : null;
2056 if (file.type == 0 && rec_mode != null)
2057 rec = rec_mode.getSelectedIndex();
2058 String rv[] = filemgr.get_text(
2059 "chmod.cgi?path="+filemgr.urlize(file.path)+
2060 (perms < 0 ? "" : "&perms="+perms)+
2061 (user_str == null ? "" :
2062 "&user="+filemgr.urlize(user_str))+
2063 (group_str == null ? "" :
2064 "&group="+filemgr.urlize(group_str))+
2066 (linkto==null ? "" :
2067 "&linkto="+filemgr.urlize(linkto.getText())));
2068 if (rv[0].length() > 0) {
2069 // Something went wrong
2070 new ErrorWindow(filemgr.text("info_efailed",
2074 // Update all changed file objects
2076 file.linkto = linkto.getText();
2078 update_file(file, perms, false);
2079 else if (rec == 1) {
2080 // Update files in this directory
2081 update_file(file, perms, false);
2082 recurse_files(file, perms, false);
2084 else if (rec == 2) {
2085 // Update files and subdirs
2086 update_file(file, perms, false);
2087 recurse_files(file, perms, true);
2090 // Update directory list
2091 int os = filemgr.files.selected();
2092 filemgr.show_files(filemgr.showing_files);
2093 filemgr.files.select(os);
2097 else if (b == size_b) {
2098 // Get the size of the directory recursively
2099 String l[] = filemgr.get_text("size.cgi?dir="+
2100 filemgr.urlize(file.path));
2101 if (l[0].length() > 0) {
2102 new ErrorWindow(filemgr.text("info_size", l[0]));
2104 StringTokenizer tok = new StringTokenizer(l[1], " ");
2105 String bytes_str = tok.nextToken();
2106 files.setText(tok.nextToken());
2107 dirs.setText(tok.nextToken());
2108 bytes.setText(tok.nextToken()+" "+tok.nextToken());
2116 void update_file(RemoteFile f, int perms, boolean perms_only)
2118 f.user = user.getText();
2119 f.group = group.getText();
2121 f.perms = (perms & 0777) | (f.perms & 037777777000);
2126 void recurse_files(RemoteFile f, int perms, boolean do_subs)
2128 if (f.list == null) return;
2129 for(int i=0; i<f.list.length; i++) {
2130 RemoteFile ff = f.list[i];
2131 if (ff.type == 5) continue;
2132 else if (ff.type == 0) {
2134 update_file(ff, perms, false);
2135 recurse_files(ff, perms, true);
2138 else update_file(ff, perms, true);
2142 void setup_leftright(Panel m, Panel l, Panel r)
2144 m.setLayout(new BorderLayout());
2145 Panel p = new Panel();
2146 p.setLayout(new BorderLayout());
2149 l.setLayout(new GridLayout(0, 1));
2150 r.setLayout(new GridLayout(0, 1));
2154 void add_item(String t, Component c, Panel l, Panel r)
2156 l.add(new Label(t));
2157 Panel p = new Panel();
2158 p.setLayout(new BorderLayout());
2165 if (octal != null) {
2166 String oct = Integer.toOctalString(get_perms());
2167 while(oct.length() < 4)
2176 return -1; // Cannot edit
2179 perms |= (file.perms & 0x800);
2181 perms |= (setuid.getState() ? 0x800 : 0);
2182 perms |= (setgid.getState() ? 0x400 : 0);
2183 perms |= user_p.getPerms();
2184 perms |= group_p.getPerms();
2185 perms |= other_p.getPerms();
2187 perms |= (file.perms & 01000);
2189 perms |= (sticky.getState() ? 01000 : 0);
2193 public boolean handleEvent(Event e)
2195 if (e.target instanceof Checkbox) {
2199 return super.handleEvent(e);
2203 class PermissionsPanel extends Panel
2205 Checkbox read, write, exec;
2208 PermissionsPanel(RemoteFile file, int base, FileManager filemgr)
2210 int perms = file.perms;
2212 setLayout(new GridLayout(1, 3));
2213 add(read = new Checkbox(filemgr.text("info_read")));
2214 read.setState((perms&(base<<2)) != 0);
2215 add(write = new Checkbox(filemgr.text("info_write")));
2216 write.setState((perms&(base<<1)) != 0);
2217 add(exec = new Checkbox(
2218 filemgr.text(file.type == RemoteFile.DIR ? "info_list"
2220 exec.setState((perms&base) != 0);
2226 rv |= (read.getState() ? (base<<2) : 0);
2227 rv |= (write.getState() ? (base<<1) : 0);
2228 rv |= (exec.getState() ? base : 0);
2233 class DeleteWindow extends FixedFrame implements CbButtonCallback
2235 CbButton delete_b, cancel_b;
2236 FileManager filemgr;
2239 DeleteWindow(FileManager p, RemoteFile ff[])
2243 setTitle(filemgr.text(ff.length > 1 ? "delete_mtitle" :
2244 ff[0].type == 0 ? "delete_dtitle" :
2247 setLayout(new BorderLayout());
2248 if (ff.length > 1) {
2249 add("North", new Label(filemgr.text("delete_mdesc")));
2250 Panel mp = new Panel();
2251 mp.setLayout(new GridLayout(ff.length, 1));
2252 for(int i=0; i<ff.length; i++)
2253 mp.add(new Label(ff[i].path));
2257 add("Center", new MultiLabel(filemgr.text(
2258 ff[0].type == 0 ? "delete_ddesc" : "delete_fdesc",
2260 Panel bot = new Panel();
2261 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
2262 bot.add(delete_b = new CbButton(filemgr.get_image("save.gif"),
2263 filemgr.text("delete"),
2264 CbButton.LEFT, this));
2265 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2266 filemgr.text("cancel"),
2267 CbButton.LEFT, this));
2269 Util.recursiveBody(this);
2274 public void click(CbButton b)
2276 if (b == delete_b) {
2277 // Delete the file or directory
2278 boolean need_redraw = false, need_reshow = false;
2279 for(int i=0; i<files.length; i++) {
2280 RemoteFile file = files[i];
2281 String rv[] = filemgr.get_text("delete.cgi?file="+
2282 filemgr.urlize(file.path));
2283 if (rv[0].length() > 0) {
2284 new ErrorWindow(filemgr.text("delete_efailed",
2289 // done the deed.. update data structures
2290 RemoteFile pf = file.directory;
2292 if (filemgr.showing_files == pf) {
2293 // Need to refresh the list as well..
2297 FileNode node = (FileNode)filemgr.nodemap.get(
2299 FileNode pnode = (FileNode)filemgr.nodemap.get(
2302 // Take the directory out of the tree..
2303 pnode.ch.removeElement(node);
2308 if (need_reshow) filemgr.show_files(filemgr.showing_files);
2309 if (need_redraw) filemgr.dirs.redraw();
2312 else if (b == cancel_b)
2317 class MkdirWindow extends FixedFrame implements CbButtonCallback
2319 FileManager filemgr;
2321 CbButton create_b, cancel_b;
2323 MkdirWindow(String d, FileManager p)
2326 setTitle(filemgr.text("mkdir_title"));
2327 setLayout(new BorderLayout());
2328 add("West", new Label(filemgr.text("mkdir_dir")));
2329 add("Center", dir = new TextField(d.equals("/") ? "/" : d+"/", 40));
2330 dir.setFont(filemgr.fixed);
2331 dir.select(dir.getText().length(), dir.getText().length());
2332 Panel bot = new Panel();
2333 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
2334 bot.add(create_b = new CbButton(filemgr.get_image("save.gif"),
2335 filemgr.text("create"),
2336 CbButton.LEFT, this));
2337 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2338 filemgr.text("cancel"),
2339 CbButton.LEFT, this));
2341 Util.recursiveBody(this);
2346 public void click(CbButton b)
2348 if (b == create_b) {
2349 // Find the filemgr directory
2350 String path = dir.getText();
2351 path = filemgr.trim_path(path);
2352 int sl = path.lastIndexOf('/');
2353 RemoteFile par = filemgr.find_directory(
2354 path.substring(0, sl), false);
2355 if (par.find(path.substring(sl+1)) != null) {
2356 new ErrorWindow(filemgr.text("mkdir_eexists", path));
2359 String rv[] = filemgr.get_text("mkdir.cgi?dir="+
2360 filemgr.urlize(path));
2361 if (rv[0].length() > 0) {
2362 new ErrorWindow(filemgr.text("mkdir_efailed", rv[0]));
2365 RemoteFile file = new RemoteFile(filemgr, rv[1], par);
2367 FileNode parnode = (FileNode)filemgr.nodemap.get(par);
2368 if (parnode != null) {
2370 parnode.add(new FileNode(file));
2371 filemgr.dirs.redraw();
2373 filemgr.show_files(filemgr.showing_files);
2380 class LinkWindow extends FixedFrame implements CbButtonCallback
2382 FileManager filemgr;
2384 CbButton create_b, cancel_b;
2386 LinkWindow(String d, FileManager p)
2389 setLayout(new BorderLayout());
2390 setTitle(filemgr.text("link_title"));
2391 Panel l = new Panel(), r = new Panel();
2392 l.setLayout(new GridLayout(0, 1));
2393 l.add(new Label(filemgr.text("link_from")));
2394 l.add(new Label(filemgr.text("link_to")));
2395 r.setLayout(new GridLayout(0, 1));
2396 r.add(from = new TextField(d.equals("/") ? "/" : d+"/", 40));
2397 from.setFont(filemgr.fixed);
2398 from.select(from.getText().length(), from.getText().length());
2399 r.add(to = new TextField());
2400 to.setFont(filemgr.fixed);
2401 add("West", l); add("Center", r);
2402 Panel bot = new Panel();
2403 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
2404 bot.add(create_b = new CbButton(filemgr.get_image("save.gif"),
2405 filemgr.text("create"),
2406 CbButton.LEFT, this));
2407 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2408 filemgr.text("cancel"),
2409 CbButton.LEFT, this));
2411 Util.recursiveBody(this);
2416 public void click(CbButton b)
2418 if (b == create_b) {
2420 String from_str = from.getText().trim();
2421 if (!from_str.startsWith("/")) {
2422 new ErrorWindow(filemgr.text("link_efrom", from_str));
2425 int sl = from_str.lastIndexOf('/');
2426 String par_str = from_str.substring(0, sl),
2427 file_str = from_str.substring(sl+1);
2428 RemoteFile par = filemgr.find_directory(par_str, false);
2429 if (par == null) return;
2430 if (par.find(file_str) != null) {
2431 new ErrorWindow(filemgr.text("link_eexists", from_str));
2435 // Create the actual link
2436 String rv[] = filemgr.get_text("makelink.cgi?from="+
2437 filemgr.urlize(from_str)+"&to="+
2438 filemgr.urlize(to.getText()));
2439 if (rv[0].length() > 0) {
2440 new ErrorWindow(filemgr.text("link_efailed", rv[0]));
2443 RemoteFile file = new RemoteFile(filemgr, rv[1], par);
2445 filemgr.show_files(filemgr.showing_files);
2448 else if (b == cancel_b)
2453 class RenameWindow extends FixedFrame implements CbButtonCallback
2455 FileManager filemgr;
2457 TextField oldname, newname;
2458 CbButton rename_b, cancel_b;
2460 RenameWindow(FileManager p, RemoteFile f)
2462 filemgr = p; file = f;
2463 setLayout(new BorderLayout());
2464 setTitle(filemgr.text("rename_title", file.path));
2465 Panel l = new Panel(), r = new Panel();
2466 l.setLayout(new GridLayout(0, 1));
2467 l.add(new Label(filemgr.text("rename_old")));
2468 l.add(new Label(filemgr.text("rename_new")));
2469 r.setLayout(new GridLayout(0, 1));
2470 r.add(oldname = new TextField(file.name, 20));
2471 oldname.setEditable(false);
2472 oldname.setFont(filemgr.fixed);
2473 r.add(newname = new TextField(file.name, 20));
2474 newname.select(file.name.length(), file.name.length());
2475 newname.setFont(filemgr.fixed);
2476 add("West", l); add("Center", r);
2478 Panel bot = new Panel();
2479 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
2480 bot.add(rename_b = new CbButton(filemgr.get_image("save.gif"),
2481 filemgr.text("rename_ok"),
2482 CbButton.LEFT, this));
2483 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2484 filemgr.text("cancel"),
2485 CbButton.LEFT, this));
2489 Util.recursiveBody(this);
2492 public void click(CbButton b)
2494 if (b == rename_b) {
2495 // Work out destination file and directory
2496 String newstr = newname.getText().trim();
2497 if (newstr.length() == 0) return;
2500 if (newstr.indexOf('/') >= 0) {
2502 if (newstr.startsWith("/")) {
2503 // Some absolute path
2507 // Relative to this dir
2508 newpath = file.directory.path+"/"+newstr;
2510 int sl = newpath.lastIndexOf('/');
2511 String newdir = sl == 0 ? "/" : newpath.substring(0,sl);
2512 destdir = filemgr.find_directory(newdir, false);
2516 destdir = file.directory;
2517 int sl = file.path.lastIndexOf('/');
2518 newpath = file.path.substring(0, sl)+"/"+newstr;
2521 // Work out filename only
2522 int sl = newpath.lastIndexOf('/');
2523 newstr = newpath.substring(sl+1);
2525 // Check for an existing file
2526 RemoteFile already = destdir.find(newstr);
2527 if (already != null) {
2528 new ErrorWindow(filemgr.text("rename_eexists", newstr));
2532 // Rename the real file
2533 String rv[] = filemgr.get_text(
2534 "rename.cgi?old="+filemgr.urlize(file.path)+
2535 "&new="+filemgr.urlize(newpath));
2536 if (rv[0].length() > 0) {
2537 new ErrorWindow(filemgr.text("rename_efailed", rv[0]));
2541 // Update data structure
2543 file.path = newpath;
2544 file.directory.delete(file);
2547 file.directory = destdir;
2549 FileNode parnode = (FileNode)filemgr.nodemap.get(file.directory);
2550 FileNode filenode = (FileNode)filemgr.nodemap.get(file);
2551 if (parnode != null && filenode != null) {
2552 // Need to refresh tree
2553 filenode.text = file.name;
2554 parnode.ch.removeElement(filenode);
2555 parnode.add(filenode);
2557 filemgr.dirs.redraw();
2560 filemgr.show_files(filemgr.showing_files);
2563 else if (b == cancel_b)
2568 class OverwriteWindow extends FixedFrame implements CbButtonCallback
2570 FileManager filemgr;
2571 RemoteFile src, already;
2573 CbButton ok, cancel;
2577 OverwriteWindow(FileManager p, RemoteFile a, RemoteFile s, int i)
2579 filemgr = p; src = s; already = a; idx = i;
2580 mode = filemgr.cut_mode;
2581 setLayout(new BorderLayout());
2582 setTitle(filemgr.text("over_title"));
2584 new MultiLabel(filemgr.text("over_msg", already.path), 30, 0));
2585 add("West", new Label(filemgr.text("over_new")));
2586 add("East", newname = new TextField(a.name, 30));
2587 newname.setFont(filemgr.fixed);
2589 Panel bot = new Panel();
2590 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
2591 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
2592 filemgr.text("over_ok"),
2593 CbButton.LEFT, this));
2594 bot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
2595 filemgr.text("cancel"),
2596 CbButton.LEFT, this));
2598 Util.recursiveBody(this);
2603 public void click(CbButton b)
2607 else if (b == ok && newname.getText().length() > 0) {
2608 // paste the file, but with a new name
2609 RemoteFile ap = already.directory;
2610 RemoteFile newalready = ap.find(newname.getText());
2611 if (newalready == src) {
2612 new ErrorWindow(filemgr.text("paste_eself"));
2615 if (newalready != null && (newalready.type == 0 ||
2616 newalready.type == 5)) {
2618 filemgr.text("paste_eover", newalready.path));
2621 String dpath = (ap.path.equals("/") ? "/" :
2622 ap.path+"/")+newname.getText();
2623 RemoteFile nf = filemgr.paste_file(src, already.directory,
2624 dpath, newalready, mode);
2625 if (filemgr.cut_mode && nf != null) {
2626 // Paste from the destination path from now on
2627 filemgr.cut_buffer[idx] = nf;
2642 SambaShare(String l)
2644 StringSplitter tok = new StringSplitter(l, ':');
2645 path = tok.nextToken();
2646 available = tok.nextToken().equals("1");
2647 writable = tok.nextToken().equals("1");
2648 guest = Integer.parseInt(tok.nextToken());
2649 comment = tok.nextToken();
2652 SambaShare(String p, boolean a, boolean w, int g, String c)
2663 return "path="+FileManager.urlize(path)+
2664 "&available="+(available ? 1 : 0)+
2665 "&writable="+(writable ? 1 : 0)+
2667 "&comment="+FileManager.urlize(comment);
2671 class DFSAdminExport
2675 String ro, rw, root;
2677 DFSAdminExport(String l)
2679 StringSplitter tok = new StringSplitter(l, ':');
2680 path = tok.nextToken();
2681 ro = tok.nextToken();
2682 rw = tok.nextToken();
2683 root = tok.nextToken();
2684 desc = tok.nextToken();
2687 DFSAdminExport(String p, String d, String ro, String rw, String root)
2696 static String[] split(String s)
2698 StringTokenizer stok = new StringTokenizer(s, " ");
2699 String rv[] = new String[stok.countTokens()];
2700 for(int i=0; i<rv.length; i++)
2701 rv[i] = stok.nextToken();
2707 return "path="+FileManager.urlize(path)+
2708 "&ro="+FileManager.urlize(ro)+
2709 "&rw="+FileManager.urlize(rw)+
2710 "&root="+FileManager.urlize(root)+
2711 "&desc="+FileManager.urlize(desc);
2722 LinuxExport(String l)
2724 StringSplitter tok = new StringSplitter(l, ':');
2725 path = tok.nextToken();
2726 int c = tok.countTokens() / 3;
2727 host = new String[c];
2728 ro = new boolean[c];
2729 squash = new int[c];
2730 for(int i=0; tok.hasMoreTokens(); i++) {
2731 host[i] = tok.nextToken();
2732 ro[i] = tok.nextToken().equals("1");
2733 squash[i] = Integer.parseInt(tok.nextToken());
2737 LinuxExport(String p, String h[], String r[], String s[])
2744 String rv = "path="+FileManager.urlize(path)+
2745 "&count="+host.length;
2746 for(int i=0; i<host.length; i++) {
2747 rv += "&host"+i+"="+FileManager.urlize(host[i]);
2748 rv += "&ro"+i+"="+(ro[i] ? 1 : 0);
2749 rv += "&squash"+i+"="+squash[i];
2755 class SharingWindow extends FixedFrame implements CbButtonCallback
2757 CbButton save_b, cancel_b;
2759 FileManager filemgr;
2761 DFSAdminExport dexport;
2762 LinuxExport lexport;
2763 Checkbox samba_on, samba_off;
2764 Checkbox writable_on, writable_off;
2765 Checkbox available_on, available_off;
2766 Checkbox guest_on, guest_off, guest_only;
2770 Checkbox nfs_on, nfs_off;
2771 TextField rwhosts, rohosts, roothosts;
2772 Checkbox rw[] = new Checkbox[3], ro[] = new Checkbox[3],
2773 root[] = new Checkbox[3];
2776 Choice lro[], squash[];
2778 SharingWindow(RemoteFile f, FileManager p)
2780 file = f; filemgr = p;
2781 setTitle(filemgr.text("share_title", file.path));
2782 sshare = (SambaShare)filemgr.stab.get(file.path);
2783 Object nshare = filemgr.ntab.get(file.path);
2784 if (filemgr.nfsmode == 1)
2785 lexport = (LinuxExport)nshare;
2786 else if (filemgr.nfsmode == 2)
2787 dexport = (DFSAdminExport)nshare;
2790 setLayout(new BorderLayout());
2791 Panel samba = new Panel(), sl = new Panel(), sr = new Panel();
2792 samba.setLayout(new BorderLayout());
2793 Panel st = new Panel();
2794 st.setLayout(new GridLayout(2, 1));
2795 CheckboxGroup sg = new CheckboxGroup();
2796 st.add(samba_off = new Checkbox(filemgr.text("share_soff"), sg,
2798 st.add(samba_on = new Checkbox(filemgr.text("share_son"), sg,
2800 samba.add("North", st);
2802 Panel stop = new LinedPanel(filemgr.text("share_sheader"));
2803 setup_leftright(stop, sl, sr);
2805 comment = new TextField(sshare == null ? "" : sshare.comment, 25);
2806 comment.setFont(filemgr.fixed);
2807 add_item(filemgr.text("share_comment"), comment, sl, sr);
2809 Panel ap = new Panel();
2810 ap.setLayout(new GridLayout(1, 0));
2811 CheckboxGroup ag = new CheckboxGroup();
2812 ap.add(available_on = new Checkbox(filemgr.text("yes"), ag,
2813 sshare == null || sshare.available));
2814 ap.add(available_off = new Checkbox(filemgr.text("no"), ag,
2815 sshare != null && !sshare.available));
2816 add_item(filemgr.text("share_available"), ap, sl, sr);
2818 Panel wp = new Panel();
2819 wp.setLayout(new GridLayout(1, 0));
2820 CheckboxGroup wg = new CheckboxGroup();
2821 wp.add(writable_on = new Checkbox(filemgr.text("yes"), wg,
2822 sshare == null || sshare.writable));
2823 wp.add(writable_off = new Checkbox(filemgr.text("no"), wg,
2824 sshare != null && !sshare.writable));
2825 add_item(filemgr.text("share_writable"), wp, sl, sr);
2827 Panel gp = new Panel();
2828 gp.setLayout(new GridLayout(1, 0));
2829 CheckboxGroup gg = new CheckboxGroup();
2830 gp.add(guest_only = new Checkbox(filemgr.text("share_only"), gg,
2831 sshare != null && sshare.guest == 2));
2832 gp.add(guest_on = new Checkbox(filemgr.text("yes"), gg,
2833 sshare == null || sshare.guest == 1));
2834 gp.add(guest_off = new Checkbox(filemgr.text("no"), gg,
2835 sshare != null && sshare.guest == 0));
2836 add_item(filemgr.text("share_guest"), gp, sl, sr);
2838 samba.add("Center", stop);
2841 Panel nfs = new Panel(), nl = new Panel(), nr = new Panel();
2842 nfs.setLayout(new BorderLayout());
2843 Panel nt = new Panel();
2844 nt.setLayout(new GridLayout(2, 1));
2845 CheckboxGroup ng = new CheckboxGroup();
2846 nt.add(nfs_off = new Checkbox(filemgr.text("share_noff"), ng,
2848 nt.add(nfs_on = new Checkbox(filemgr.text("share_non"), ng,
2850 nfs.add("North", nt);
2852 Panel ntop = new LinedPanel(filemgr.text("share_nheader"));
2853 setup_leftright(ntop, nl, nr);
2854 if (filemgr.nfsmode == 1) {
2855 // Linux export mode
2856 nl.setLayout(new GridLayout(0, 1, 2, 2));
2857 nr.setLayout(new GridLayout(0, 1, 2, 2));
2858 nl.add(new Label(filemgr.text("share_host")));
2859 nr.add(new Label(filemgr.text("share_opts")));
2860 int c = lexport==null ? 0 : lexport.host.length;
2861 host = new TextField[c+1];
2862 lro = new Choice[c+1];
2863 squash = new Choice[c+1];
2864 for(int i=0; i<c; i++) {
2865 host[i] = new TextField(lexport.host[i], 20);
2866 host[i].setFont(filemgr.fixed);
2867 lro[i] = robox(lexport.ro[i]);
2868 squash[i] = squashbox(lexport.squash[i]);
2870 nr.add(opts_panel(lro[i], squash[i]));
2872 host[c] = new TextField("", 20);
2873 host[c].setFont(filemgr.fixed);
2874 lro[c] = robox(false);
2875 squash[c] = squashbox(1);
2877 nr.add(opts_panel(lro[c], squash[c]));
2879 else if (filemgr.nfsmode == 2) {
2880 // Solaris share mode
2881 desc = new TextField(dexport == null ? "" : dexport.desc, 25);
2882 desc.setFont(filemgr.fixed);
2883 add_item(filemgr.text("share_desc"), desc, nl, nr);
2885 rohosts = add_hosts(filemgr.text("share_ro"),
2886 dexport == null ? "-" : dexport.ro,
2888 rwhosts = add_hosts(filemgr.text("share_rw"),
2889 dexport == null ? "-" : dexport.rw,
2891 roothosts = add_hosts(filemgr.text("share_root"),
2892 dexport == null ? "-" : dexport.root,
2894 root[1].getParent().remove(root[1]);
2896 else if (filemgr.nfsmode == 3) {
2898 nfs.add("Center", ntop);
2900 // Add the appropriate tabs
2901 if (filemgr.sambamode && filemgr.nfsmode != 0) {
2902 TabbedPanel tab = new TabbedPanel();
2903 tab.addItem(filemgr.text("share_samba"), samba);
2904 tab.addItem(filemgr.text("share_nfs"), nfs);
2907 else if (filemgr.sambamode)
2908 add("Center", samba);
2909 else if (filemgr.nfsmode != 0)
2912 // Create save and cancel buttons
2913 Panel bot = new Panel();
2914 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
2915 bot.add(save_b = new CbButton(filemgr.get_image("save.gif"),
2916 filemgr.text("save"),
2917 CbButton.LEFT, this));
2918 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2919 filemgr.text("cancel"),
2920 CbButton.LEFT, this));
2922 Util.recursiveBody(this);
2927 public void click(CbButton b)
2930 // Update samba settings on server
2931 if (sshare != null && samba_on.getState()) {
2933 sshare.available = available_on.getState();
2934 sshare.writable = writable_on.getState();
2935 sshare.guest = guest_only.getState() ? 2 :
2936 guest_on.getState() ? 1 : 0;
2937 sshare.comment = comment.getText();
2938 String rv[] = filemgr.get_text(
2939 "save_share.cgi?"+sshare.params());
2941 else if (sshare != null) {
2943 String rv[] = filemgr.get_text(
2944 "save_share.cgi?delete=1&"+sshare.params());
2945 filemgr.stab.remove(sshare.path);
2947 else if (samba_on.getState()) {
2949 sshare = new SambaShare(file.path,
2950 available_on.getState(),
2951 writable_on.getState(),
2952 guest_only.getState() ? 2 :
2953 guest_on.getState() ? 1 : 0,
2955 filemgr.stab.put(sshare.path, sshare);
2956 String rv[] = filemgr.get_text(
2957 "save_share.cgi?new=1&"+sshare.params());
2960 // Update NFS settings on server
2961 if (filemgr.nfsmode == 1) {
2962 if (lexport != null && nfs_on.getState()) {
2964 export_options(lexport);
2965 String rv[] = filemgr.get_text(
2966 "save_export.cgi?"+lexport.params());
2968 else if (lexport != null) {
2970 String rv[] = filemgr.get_text(
2971 "save_export.cgi?delete=1&"+lexport.params());
2972 filemgr.ntab.remove(lexport.path);
2974 else if (nfs_on.getState()) {
2976 lexport = new LinuxExport(file.path, null,
2978 export_options(lexport);
2979 String rv[] = filemgr.get_text(
2980 "save_export.cgi?new=1&"+lexport.params());
2981 filemgr.ntab.put(lexport.path, lexport);
2984 else if (filemgr.nfsmode == 2) {
2985 if (dexport != null && nfs_on.getState()) {
2987 dexport.desc = desc.getText();
2988 dexport.ro = ro[0].getState() ? "-" :
2989 ro[1].getState() ? "" :
2991 dexport.rw = rw[0].getState() ? "-" :
2992 rw[1].getState() ? "" :
2994 dexport.root = root[0].getState() ? "-" :
2995 roothosts.getText();
2996 String rv[] = filemgr.get_text(
2997 "save_export.cgi?"+dexport.params());
2999 else if (dexport != null) {
3001 String rv[] = filemgr.get_text(
3002 "save_export.cgi?delete=1&"+dexport.params());
3003 filemgr.ntab.remove(dexport.path);
3005 else if (nfs_on.getState()) {
3006 // Creating new share
3007 dexport = new DFSAdminExport(file.path,
3009 ro[0].getState() ? "-" :
3010 ro[1].getState() ? "" :
3012 rw[0].getState() ? "-" :
3013 rw[1].getState() ? "" :
3015 root[0].getState() ? "-" :
3016 roothosts.getText());
3017 String rv[] = filemgr.get_text(
3018 "save_export.cgi?new=1&"+dexport.params());
3019 filemgr.ntab.put(dexport.path, dexport);
3022 else if (filemgr.nfsmode == 3) {
3025 filemgr.show_files(filemgr.showing_files);
3028 else if (b == cancel_b)
3032 void setup_leftright(Panel m, Panel l, Panel r)
3034 m.setLayout(new BorderLayout());
3035 Panel p = new Panel();
3036 p.setLayout(new BorderLayout());
3039 l.setLayout(new GridLayout(0, 1));
3040 r.setLayout(new GridLayout(0, 1));
3044 void add_item(String t, Component c, Panel l, Panel r)
3046 l.add(new Label(t));
3047 Panel p = new Panel();
3048 p.setLayout(new BorderLayout());
3053 TextField add_hosts(String name, String v, Checkbox cb[],
3056 Panel p = new Panel();
3057 p.setLayout(new GridLayout(1, 3));
3058 CheckboxGroup g = new CheckboxGroup();
3059 p.add(cb[0] = new Checkbox(filemgr.text("share_none"), g,
3061 p.add(cb[1] = new Checkbox(filemgr.text("share_all"), g,
3063 p.add(cb[2] = new Checkbox(filemgr.text("share_listed"), g,
3065 add_item(name, p, l, r);
3066 TextField t = new TextField(v.equals("-") ? "" : v, 25);
3067 t.setFont(filemgr.fixed);
3068 add_item("", t, l, r);
3072 Choice squashbox(int s)
3074 Choice rv = new Choice();
3075 rv.addItem(filemgr.text("share_s0"));
3076 rv.addItem(filemgr.text("share_s1"));
3077 rv.addItem(filemgr.text("share_s2"));
3082 Choice robox(boolean r)
3084 Choice rv = new Choice();
3085 rv.addItem(filemgr.text("share_lrw"));
3086 rv.addItem(filemgr.text("share_lro"));
3087 rv.select(r ? 1 : 0);
3091 Panel opts_panel(Component ro, Component squash)
3093 Panel p = new Panel();
3094 p.setLayout(new BorderLayout());
3096 p.add("East", squash);
3100 void export_options(LinuxExport e)
3103 for(int i=0; i<host.length; i++)
3104 if (host[i].getText().length() > 0)
3106 e.host = new String[c];
3107 e.ro = new boolean[c];
3108 e.squash = new int[c];
3109 for(int i=0,j=0; i<host.length; i++) {
3110 if (host[i].getText().trim().length() > 0) {
3111 e.host[j] = host[i].getText();
3112 e.ro[j] = lro[i].getSelectedIndex() == 1;
3113 e.squash[j] = squash[i].getSelectedIndex();
3121 class SearchWindow extends FixedFrame
3122 implements CbButtonCallback,MultiColumnCallback
3126 CbButton search_b, cancel_b, down_b;
3127 FileManager filemgr;
3128 TextField dir, match, user, group;
3129 Checkbox uany, usel, gany, gsel;
3131 Checkbox sany, smore, sless;
3132 TextField more, less;
3134 String types[] = { "", "f", "d", "l", "p" };
3136 RemoteFile results[];
3138 SearchWindow(String d, FileManager p)
3141 setTitle(filemgr.text("search_title"));
3144 setLayout(new BorderLayout());
3145 tab = new TabbedPanel();
3146 Panel search = new Panel();
3147 search.setLayout(new BorderLayout());
3148 tab.addItem(filemgr.text("search_crit"), search);
3149 Panel l = new Panel(), r = new Panel();
3150 l.setLayout(new GridLayout(0, 1));
3151 r.setLayout(new GridLayout(0, 1));
3153 String cols[] = { "", filemgr.text("right_name"),
3154 filemgr.text("right_size") };
3155 float widths[] = { .07f, .78f, .15f };
3156 list = new MultiColumn(cols, this);
3157 list.setWidths(widths);
3158 list.setDrawLines(false);
3159 list.setFont(filemgr.fixed);
3160 tab.addItem(filemgr.text("search_list"), list);
3162 add_item(filemgr.text("search_dir"), dir = new TextField(d, 30), l, r);
3163 dir.setFont(filemgr.fixed);
3166 add_item(filemgr.text("search_match"), match = new TextField(20), l, r);
3167 match.setFont(filemgr.fixed);
3169 if (filemgr.search_contents) {
3171 add_item(filemgr.text("search_cont"),
3172 cont = new TextField(30), l, r);
3173 cont.setFont(filemgr.fixed);
3176 // User or group owners
3177 if (filemgr.can_users) {
3178 Panel up = new Panel();
3179 up.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
3180 CheckboxGroup ug = new CheckboxGroup();
3181 up.add(uany = new Checkbox(filemgr.text("search_any"), ug, true));
3182 up.add(usel = new Checkbox("", ug, false));
3183 up.add(user = new TextField(10));
3184 user.setFont(filemgr.fixed);
3185 add_item(filemgr.text("search_user"), up, l, r);
3187 Panel gp = new Panel();
3188 gp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
3189 CheckboxGroup gg = new CheckboxGroup();
3190 gp.add(gany = new Checkbox(filemgr.text("search_any"), gg, true));
3191 gp.add(gsel = new Checkbox("", gg, false));
3192 gp.add(group = new TextField(10));
3193 group.setFont(filemgr.fixed);
3194 add_item(filemgr.text("search_group"), gp, l, r);
3198 if (!filemgr.follow_links) {
3199 type = new Choice();
3200 for(int i=0; i<types.length; i++)
3201 type.addItem(filemgr.text("search_types_"+types[i]));
3202 add_item(filemgr.text("search_type"), type, l, r);
3206 CheckboxGroup sg = new CheckboxGroup();
3207 add_item(filemgr.text("search_size"),
3208 sany = new Checkbox(filemgr.text("search_any"), sg, true),
3210 Panel mp = new Panel();
3211 mp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
3212 mp.add(smore = new Checkbox(filemgr.text("search_more"), sg, false));
3213 mp.add(more = new TextField(10));
3214 more.setFont(filemgr.fixed);
3215 add_item("", mp, l, r);
3216 Panel lp = new Panel();
3217 lp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
3218 lp.add(sless = new Checkbox(filemgr.text("search_less"), sg, false));
3219 lp.add(less = new TextField(10));
3220 less.setFont(filemgr.fixed);
3221 add_item("", lp, l, r);
3223 if (filemgr.got_filesystems) {
3224 // Search past mounts
3225 CheckboxGroup xg = new CheckboxGroup();
3226 Panel xp = new Panel();
3227 xp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
3228 xp.add(xoff = new Checkbox(filemgr.text("yes"), xg, true));
3229 xp.add(xon = new Checkbox(filemgr.text("no"), xg, false));
3230 add_item(filemgr.text("search_xdev"), xp, l, r);
3233 search.add("West", l); search.add("East", r);
3236 // Create search and cancel buttons
3237 Panel bot = new Panel();
3238 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3239 bot.add(down_b = new CbButton(filemgr.get_image("down.gif"),
3240 filemgr.text("search_down"),
3241 CbButton.LEFT, this));
3242 bot.add(search_b = new CbButton(filemgr.get_image("save.gif"),
3243 filemgr.text("search_ok"),
3244 CbButton.LEFT, this));
3245 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
3246 filemgr.text("cancel"),
3247 CbButton.LEFT, this));
3249 Util.recursiveBody(this);
3254 void add_item(String t, Component c, Panel l, Panel r)
3256 l.add(new Label(t));
3257 Panel p = new Panel();
3258 p.setLayout(new BorderLayout());
3263 public void click(CbButton b)
3267 else if (b == search_b) {
3268 // validate inputs and build search URL
3269 String url = "search.cgi";
3270 String d = dir.getText().trim();
3271 if (d.length() == 0 || d.charAt(0) != '/') {
3272 new ErrorWindow(filemgr.text("search_edir"));
3275 url += "?dir="+filemgr.urlize(d);
3276 String mt = match.getText().trim();
3277 if (mt.length() == 0) {
3279 //new ErrorWindow(filemgr.text("search_ematch"));
3282 url += "&match="+filemgr.urlize(mt);
3283 if (type != null && type.getSelectedIndex() > 0)
3284 url += "&type="+types[type.getSelectedIndex()];
3285 if (usel != null && usel.getState()) {
3286 String u = user.getText().trim();
3287 if (u.length() == 0) {
3288 new ErrorWindow(filemgr.text("search_euser"));
3291 url += "&user="+filemgr.urlize(u);
3293 if (gsel != null && gsel.getState()) {
3294 String g = group.getText().trim();
3295 if (g.length() == 0) {
3296 new ErrorWindow(filemgr.text("search_egroup"));
3299 url += "&group="+filemgr.urlize(g);
3301 if (smore.getState()) {
3302 String m = more.getText().trim();
3303 try { Integer.parseInt(m); }
3304 catch(Exception e) {
3305 new ErrorWindow(filemgr.text("search_esize"));
3308 url += "&size=%2B"+m+"c";
3310 else if (sless.getState()) {
3311 String l = less.getText().trim();
3312 try { Integer.parseInt(l); }
3313 catch(Exception e) {
3314 new ErrorWindow(filemgr.text("search_esize"));
3317 url += "&size=%2D"+l+"c";
3319 if (xon != null && xon.getState())
3321 if (cont != null && cont.getText().trim().length() > 0)
3322 url += "&cont="+filemgr.urlize(cont.getText());
3324 // send off the search
3325 setCursor(WAIT_CURSOR);
3326 String f[] = filemgr.get_text(url);
3327 if (f[0].length() > 0) {
3328 new ErrorWindow(f[0]);
3331 Object rows[][] = new Object[f.length-1][];
3332 results = new RemoteFile[f.length-1];
3333 for(int i=1; i<f.length; i++) {
3334 RemoteFile r = new RemoteFile(filemgr, f[i], null);
3336 Object row[] = rows[i-1] = new Object[3];
3337 row[0] = filemgr.get_image(RemoteFile.tmap[r.type]);
3340 row[2] = filemgr.spad(r.size, 5)+" B";
3341 else if (r.size < 1000000)
3342 row[2] = filemgr.spad(r.size/1000, 5)+" kB";
3344 row[2] = filemgr.spad(r.size/1000000, 5)+" MB";
3347 list.addItems(rows);
3348 tab.select(filemgr.text("search_list"));
3349 setCursor(DEFAULT_CURSOR);
3351 else if (b == down_b) {
3352 // Download selected file (if any)
3353 int num = list.selected();
3354 if (num < 0 || results.length == 0) {
3355 new ErrorWindow(filemgr.text("search_edown"));
3358 filemgr.download_file(results[num]);
3362 public void singleClick(MultiColumn list, int num)
3366 // go to the directory of the double-clicked file
3367 public void doubleClick(MultiColumn list, int num)
3369 RemoteFile f = results[num];
3370 int sl = f.path.lastIndexOf('/');
3371 String dir = sl == 0 ? "/" : f.path.substring(0, sl);
3372 filemgr.find_directory(dir, true);
3373 RemoteFile l[] = filemgr.showing_list;
3374 for(int i=0; i<l.length; i++) {
3375 if (l[i].name.equals(f.name)) {
3376 // select the file in the list
3377 filemgr.files.select(i+1);
3378 filemgr.files.scrollto(i+1);
3385 public void headingClicked(MultiColumn list, int col)
3390 // A popup window showing previously entered paths
3391 class HistoryWindow extends FixedFrame
3392 implements CbButtonCallback,ActionListener
3395 java.awt.List hlist;
3396 CbButton ok_b, cancel_b;
3397 FileManager filemgr;
3399 HistoryWindow(FileManager p)
3402 setTitle(filemgr.text("history_title"));
3405 hlist = new java.awt.List();
3406 for(int i=0; i<filemgr.history_list.size(); i++) {
3407 hlist.add((String)filemgr.history_list.elementAt(i));
3409 hlist.addActionListener(this);
3410 setLayout(new BorderLayout());
3411 add("Center", hlist);
3412 Panel bot = new Panel();
3413 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3414 bot.add(ok_b = new CbButton(filemgr.get_image("save.gif"),
3415 filemgr.text("history_ok"),
3416 CbButton.LEFT, this));
3417 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
3418 filemgr.text("cancel"),
3419 CbButton.LEFT, this));
3421 Util.recursiveBody(this);
3426 public void click(CbButton b)
3430 else if (b == ok_b) {
3431 // Go to the selected directory
3432 String p = hlist.getSelectedItem();
3434 filemgr.find_directory(p, true);
3440 public void actionPerformed(ActionEvent e)
3442 // List entry double-clicked .. go to it
3443 String p = hlist.getSelectedItem();
3444 filemgr.find_directory(p, true);
3448 public Dimension minimumSize()
3450 return new Dimension(300, 300);
3463 boolean mtab, fstab;
3465 FileSystem(String l)
3467 StringSplitter tok = new StringSplitter(l, ' ');
3468 mount = tok.nextToken();
3469 dev = tok.nextToken();
3470 type = tok.nextToken();
3471 String optstr = tok.nextToken();
3472 acls = tok.nextToken().equals("1");
3473 attrs = tok.nextToken().equals("1");
3474 ext = tok.nextToken().equals("1");
3475 mtab = tok.nextToken().equals("1");
3476 fstab = tok.nextToken().equals("1");
3478 StringTokenizer tok2 = new StringTokenizer(optstr, ",");
3479 opts = new String[tok2.countTokens()];
3480 for(int i=0; i<opts.length; i++)
3481 opts[i] = tok2.nextToken();
3487 FileManager filemgr;
3492 boolean read, write, exec;
3493 boolean empty_owner = false;
3495 ACLEntry(String l, ACLWindow w)
3497 filemgr = w.filemgr;
3499 StringSplitter tok = new StringSplitter(l, ':');
3500 type = tok.nextToken();
3501 if (type.equals("default")) {
3503 type = tok.nextToken();
3505 if (!type.equals("mask") && !type.equals("other")) {
3506 owner = tok.nextToken();
3507 if (owner.length() == 0)
3510 String rwx = tok.nextToken();
3511 if (rwx.length() == 0) {
3512 rwx = tok.nextToken(); // getfacl outputs a blank owner for
3513 // mask and other on some systems
3516 read = (rwx.charAt(0) == 'r');
3517 write = (rwx.charAt(1) == 'w');
3518 exec = (rwx.charAt(2) == 'x');
3521 ACLEntry(ACLWindow w)
3523 filemgr = w.filemgr;
3529 String rv[] = new String[3];
3530 String t = def ? "acltype_default_"+type : "acltype_"+type;
3531 rv[0] = filemgr.text(t);
3532 if (type.equals("mask") || type.equals("other") ||
3533 (def && owner == null))
3535 else if (owner != null)
3537 else if (type.equals("user"))
3538 rv[1] = filemgr.text("eacl_user", file.user);
3540 rv[1] = filemgr.text("eacl_group", file.group);
3542 if (read) rv[2] += filemgr.text("info_read")+" ";
3543 if (write) rv[2] += filemgr.text("info_write")+" ";
3544 if (exec) rv[2] += filemgr.text("info_exec")+" ";
3548 public String toString()
3550 String rv = def ? "default:" : "";
3552 if (!type.equals("mask") && !type.equals("other") || empty_owner)
3553 // mask and other types have no owner field at all, except
3554 // on some operating systems like FreeBSD where it is empty
3555 rv += (owner == null ? "" : owner)+":";
3556 rv += (read ? 'r' : '-');
3557 rv += (write ? 'w' : '-');
3558 rv += (exec ? 'x' : '-');
3563 class ACLEditor extends FixedFrame implements CbButtonCallback
3565 FileManager filemgr;
3570 Checkbox read, write, exec, owner1, owner2;
3573 // Editing an existing ACL entry
3574 ACLEditor(ACLWindow w, ACLEntry a)
3577 filemgr = aclwin.filemgr;
3583 // Creating a new ACL entry
3584 ACLEditor(ACLWindow w, String type, boolean def, boolean empty_owner)
3587 filemgr = aclwin.filemgr;
3588 acl = new ACLEntry(aclwin);
3591 acl.empty_owner = empty_owner;
3598 setTitle(filemgr.text(creating ? "eacl_create" : "eacl_edit"));
3599 setLayout(new BorderLayout());
3600 Panel left = new Panel();
3601 left.setLayout(new GridLayout(0, 1));
3603 Panel right = new Panel();
3604 right.setLayout(new GridLayout(0, 1));
3607 left.add(new Label(filemgr.text("eacl_acltype")));
3609 right.add(type = new TextField(
3610 (acl.def ? "default " : "")+acl.type, 20));
3611 type.setEditable(false);
3612 type.setFont(filemgr.fixed);
3614 if (!acl.type.equals("mask") && !acl.type.equals("other")) {
3615 left.add(new Label(filemgr.text("eacl_aclname")));
3617 // A default user or group ACL .. can be for
3618 // a specific user, or for the file owner
3619 Panel op = new Panel();
3620 op.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
3621 CheckboxGroup gr = new CheckboxGroup();
3622 op.add(owner1 = new Checkbox(filemgr.text("eacl_owner"),
3623 gr, acl.owner == null));
3624 op.add(owner2 = new Checkbox("",
3625 gr, acl.owner != null));
3626 op.add(owner = new TextField(
3627 acl.owner == null ? "" : acl.owner, 20));
3628 owner.setFont(filemgr.fixed);
3631 else if (creating || acl.owner != null) {
3632 // A user or group ACL for a specific user
3633 owner = new TextField(
3634 acl.owner == null ? "" : acl.owner, 20);
3635 owner.setFont(filemgr.fixed);
3639 // A user or group ACL for the file owner
3641 if (acl.type.equals("user"))
3642 str = filemgr.text("eacl_user", aclwin.file.user);
3644 str = filemgr.text("eacl_group", aclwin.file.group);
3645 TextField o = new TextField(str);
3646 o.setEditable(false);
3647 o.setFont(filemgr.fixed);
3652 left.add(new Label(filemgr.text("eacl_aclperms")));
3653 Panel pp = new Panel();
3654 pp.setLayout(new FlowLayout(FlowLayout.RIGHT));
3655 pp.add(read = new Checkbox(filemgr.text("info_read"), null, acl.read));
3656 pp.add(write = new Checkbox(filemgr.text("info_write"), null, acl.write));
3657 pp.add(exec = new Checkbox(filemgr.text("info_exec"), null, acl.exec));
3660 Panel bot = new Panel();
3661 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3662 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3663 filemgr.text("save"),
3664 CbButton.LEFT, this));
3665 if (!creating && (acl.owner != null || acl.def))
3666 bot.add(del = new CbButton(filemgr.get_image("cancel.gif"),
3667 filemgr.text("delete"),
3668 CbButton.LEFT, this));
3671 Util.recursiveBody(this);
3676 public void click(CbButton b)
3679 // Update or add the ACL entry
3680 if (owner1 != null && owner1.getState()) {
3683 else if (owner != null) {
3684 String o = owner.getText().trim();
3685 if (o.length() == 0 && !acl.def) {
3686 new ErrorWindow(filemgr.text("eacl_eowner"));
3689 acl.owner = owner.getText();
3690 if (acl.owner.length() == 0)
3693 acl.read = read.getState();
3694 acl.write = write.getState();
3695 acl.exec = exec.getState();
3697 // Add to the ACL table
3698 aclwin.acllist.addElement(acl);
3699 aclwin.acltable.addItem(acl.getRow());
3703 int idx = aclwin.acllist.indexOf(acl);
3704 aclwin.acltable.modifyItem(acl.getRow(), idx);
3708 else if (b == del) {
3709 // Remove this entry
3710 int idx = aclwin.acllist.indexOf(acl);
3711 aclwin.acllist.removeElementAt(idx);
3712 aclwin.acltable.deleteItem(idx);
3717 public void dispose()
3719 aclwin.edmap.remove(acl);
3724 class ACLWindow extends FixedFrame implements CbButtonCallback,MultiColumnCallback
3726 FileManager filemgr;
3728 Vector acllist = new Vector();
3729 Hashtable edmap = new Hashtable();
3731 CbButton ok, cancel, add;
3733 MultiColumn acltable;
3735 String acltypes[] = { "user", "group", "mask",
3736 "default user", "default group", "default other",
3739 ACLWindow(FileManager p, RemoteFile f)
3742 setTitle(p.text("eacl_title", f.path));
3747 String a[] = filemgr.get_text(
3748 "getfacl.cgi?file="+filemgr.urlize(file.path));
3749 if (a[0].length() != 0) {
3750 new ErrorWindow(filemgr.text("eacl_eacls", a[0]));
3755 setLayout(new BorderLayout());
3756 String titles[] = { filemgr.text("eacl_acltype"),
3757 filemgr.text("eacl_aclname"),
3758 filemgr.text("eacl_aclperms") };
3759 acltable = new MultiColumn(titles, this);
3760 for(int i=1; i<a.length; i++) {
3761 ACLEntry acl = new ACLEntry(a[i], this);
3762 acllist.addElement(acl);
3763 acltable.addItem(acl.getRow());
3765 add("Center", acltable);
3766 Panel abot = new Panel();
3767 abot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3768 abot.add(add = new CbButton(filemgr.get_image("add.gif"),
3769 filemgr.text("eacl_add"),
3770 CbButton.LEFT, this));
3771 int len = file.type == RemoteFile.DIR ? acltypes.length : 3;
3772 abot.add(addtype = new Choice());
3773 for(int i=0; i<len; i++) {
3774 String t = "acltype_"+acltypes[i].replace(' ', '_');
3775 addtype.addItem(filemgr.text(t));
3777 abot.add(new Label(" "));
3778 abot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3779 filemgr.text("save"),
3780 CbButton.LEFT, this));
3781 abot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
3782 filemgr.text("cancel"),
3783 CbButton.LEFT, this));
3786 Util.recursiveBody(this);
3791 public void click(CbButton b)
3794 // Check if there are any defaults, and if so there must
3795 // be default user, group and other
3796 boolean anydef = false, defuser = false,
3797 defgroup = false, defother = false;
3798 for(int i=0; i<acllist.size(); i++) {
3799 ACLEntry e = (ACLEntry)acllist.elementAt(i);
3800 if (e.def) anydef = true;
3801 if (e.def && e.owner == null) {
3802 if (e.type.equals("user")) defuser = true;
3803 if (e.type.equals("group")) defgroup = true;
3804 if (e.type.equals("other")) defother = true;
3807 if (anydef && (!defuser || !defgroup || !defother)) {
3808 new ErrorWindow(filemgr.text("eacl_edefaults"));
3814 for(int i=0; i<acllist.size(); i++)
3815 aclstr += (ACLEntry)acllist.elementAt(i)+"\n";
3816 String rv[] = filemgr.get_text("setfacl.cgi?file="+
3817 filemgr.urlize(file.path)+
3818 "&acl="+filemgr.urlize(aclstr));
3819 if (rv[0].length() > 0)
3820 new ErrorWindow(filemgr.text("eacl_efailed",
3825 else if (b == add) {
3826 // Open a window for a new ACL entry
3827 String t = acltypes[addtype.getSelectedIndex()];
3828 String d = "default ";
3829 boolean def = t.startsWith(d);
3831 t = t.substring(d.length());
3832 if (t.equals("mask")) {
3833 // Only allow one mask
3834 for(int i=0; i<acllist.size(); i++) {
3835 ACLEntry a = (ACLEntry)acllist.elementAt(i);
3836 if (a.type.equals(t) && a.def == def) {
3837 new ErrorWindow(filemgr.text(def ?
3838 "eacl_edefmask" : "eacl_emask"));
3843 // Check if owner field exists and is empty for existing
3844 // mask or other fields
3845 boolean new_empty_owner = false;
3846 for(int i=0; i<acllist.size(); i++) {
3847 ACLEntry a = (ACLEntry)acllist.elementAt(i);
3848 if ((a.type.equals("mask") || a.type.equals("other")) &&
3850 new_empty_owner = true;
3853 new ACLEditor(this, t, def, new_empty_owner);
3855 else if (b == cancel) {
3861 // Bring up an editor for an ACL
3862 public void doubleClick(MultiColumn list, int num)
3864 int idx = list.selected();
3866 ACLEntry e = (ACLEntry)acllist.elementAt(idx);
3867 ACLEditor ed = (ACLEditor)edmap.get(e);
3869 edmap.put(e, new ACLEditor(this, e));
3877 public void singleClick(MultiColumn list, int num)
3881 public void headingClicked(MultiColumn list, int col)
3886 class AttributesWindow extends FixedFrame
3887 implements CbButtonCallback,MultiColumnCallback
3889 FileManager filemgr;
3891 Vector attrlist = new Vector();
3892 Hashtable edmap = new Hashtable();
3894 CbButton ok, cancel, add;
3895 MultiColumn attrtable;
3897 AttributesWindow(FileManager p, RemoteFile f)
3900 setTitle(p.text("attr_title", f.path));
3904 // Get the attributes
3905 String a[] = filemgr.get_text(
3906 "getattrs.cgi?file="+filemgr.urlize(file.path));
3907 if (a[0].length() != 0) {
3908 new ErrorWindow(filemgr.text("attr_eattrs", a[0]));
3913 setLayout(new BorderLayout());
3914 String titles[] = { filemgr.text("attr_name"),
3915 filemgr.text("attr_value") };
3916 attrtable = new MultiColumn(titles, this);
3917 for(int i=1; i<a.length; i++) {
3918 FileAttribute at = new FileAttribute(a[i], filemgr);
3919 attrlist.addElement(at);
3920 attrtable.addItem(at.getRow());
3922 add("Center", attrtable);
3923 Panel abot = new Panel();
3924 abot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3925 abot.add(add = new CbButton(filemgr.get_image("add.gif"),
3926 filemgr.text("attr_add"),
3927 CbButton.LEFT, this));
3928 abot.add(new Label(" "));
3929 abot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3930 filemgr.text("save"),
3931 CbButton.LEFT, this));
3932 abot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
3933 filemgr.text("cancel"),
3934 CbButton.LEFT, this));
3937 Util.recursiveBody(this);
3942 public void click(CbButton b)
3945 // Save the attributes
3947 for(int i=0; i<attrlist.size(); i++) {
3948 FileAttribute at = (FileAttribute)attrlist.elementAt(i);
3949 pstr += "&name"+i+"="+filemgr.urlize(at.name)+
3950 "&value"+i+"="+filemgr.urlize(at.value);
3952 String rv[] = filemgr.get_text("setattrs.cgi?file="+
3953 filemgr.urlize(file.path)+pstr);
3954 if (rv[0].length() > 0)
3955 new ErrorWindow(filemgr.text("attr_efailed",
3960 else if (b == add) {
3961 // Open a window for a new ACL entry
3962 new AttributeEditor(this);
3964 else if (b == cancel) {
3970 // Bring up an editor for an ACL
3971 public void doubleClick(MultiColumn list, int num)
3973 int idx = list.selected();
3975 FileAttribute at = (FileAttribute)attrlist.elementAt(idx);
3976 AttributeEditor ed = (AttributeEditor)edmap.get(at);
3978 edmap.put(at, new AttributeEditor(this, at));
3986 public void singleClick(MultiColumn list, int num)
3990 public void headingClicked(MultiColumn list, int col)
4000 FileAttribute(String l, FileManager f)
4002 int eq = l.indexOf('=');
4003 name = f.un_urlize(l.substring(0, eq));
4004 value = f.un_urlize(l.substring(eq+1));
4007 FileAttribute(String n, String v)
4015 return new String[] { name, value };
4019 class AttributeEditor extends FixedFrame implements CbButtonCallback
4021 FileManager filemgr;
4022 AttributesWindow attrwin;
4029 AttributeEditor(AttributesWindow w, FileAttribute a)
4033 filemgr = w.filemgr;
4038 AttributeEditor(AttributesWindow w)
4041 attr = new FileAttribute("", "");
4042 filemgr = w.filemgr;
4049 setTitle(filemgr.text(creating ? "attr_create" : "attr_edit"));
4050 setLayout(new BorderLayout());
4052 Panel top = new Panel();
4053 top.setLayout(new GridLayout(1, 2));
4054 top.add(new Label(filemgr.text("attr_name")));
4055 top.add(name = new TextField(attr.name, 20));
4056 name.setFont(filemgr.fixed);
4059 Panel mid = new Panel();
4060 mid.setLayout(new GridLayout(1, 2));
4061 mid.add(new Label(filemgr.text("attr_value")));
4062 mid.add(value = new TextArea(attr.value, 5, 20));
4065 Panel bot = new Panel();
4066 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
4067 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
4068 filemgr.text("save"),
4069 CbButton.LEFT, this));
4071 bot.add(del = new CbButton(filemgr.get_image("cancel.gif"),
4072 filemgr.text("delete"),
4073 CbButton.LEFT, this));
4076 Util.recursiveBody(this);
4081 public void click(CbButton b)
4084 // Update or add the attribute
4085 if (name.getText().length() == 0) {
4086 new ErrorWindow(filemgr.text("attr_ename"));
4089 attr.name = name.getText();
4090 attr.value = value.getText();
4092 // Add to the attribs table
4093 attrwin.attrlist.addElement(attr);
4094 attrwin.attrtable.addItem(attr.getRow());
4098 int idx = attrwin.attrlist.indexOf(attr);
4099 attrwin.attrtable.modifyItem(attr.getRow(), idx);
4103 else if (b == del) {
4104 // Remove this entry
4105 int idx = attrwin.attrlist.indexOf(attr);
4106 attrwin.attrlist.removeElementAt(idx);
4107 attrwin.attrtable.deleteItem(idx);
4112 public void dispose()
4114 attrwin.edmap.remove(attr);
4119 class EXTWindow extends FixedFrame implements CbButtonCallback
4121 FileManager filemgr;
4124 CbButton ok, cancel;
4127 String attrs[] = { "A", "a", "c", "d", "i", "s", "S", "u" };
4128 Hashtable attrmap = new Hashtable();
4130 EXTWindow(FileManager p, RemoteFile f)
4133 setTitle(p.text("ext_title", f.path));
4137 // Get the attributes
4138 String a[] = filemgr.get_text(
4139 "getext.cgi?file="+filemgr.urlize(file.path));
4140 if (a[0].length() != 0) {
4141 new ErrorWindow(filemgr.text("ext_eattrs", a[0]));
4144 for(int i=0; i<a[1].length(); i++)
4145 attrmap.put(a[1].substring(i, i+1), "");
4148 setLayout(new BorderLayout());
4149 Panel top = new LinedPanel(filemgr.text("ext_header"));
4150 top.setLayout(new GridLayout(0, 1));
4151 cbs = new Checkbox[attrs.length];
4152 for(int i=0; i<attrs.length; i++) {
4153 cbs[i] = new Checkbox(filemgr.text("eattr_"+attrs[i]));
4154 cbs[i].setState(attrmap.get(attrs[i]) != null);
4159 Panel bot = new Panel();
4160 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
4161 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
4162 filemgr.text("save"),
4163 CbButton.LEFT, this));
4164 bot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
4165 filemgr.text("cancel"),
4166 CbButton.LEFT, this));
4169 Util.recursiveBody(this);
4174 public void click(CbButton b)
4177 // Save the attributes (including unknown ones)
4179 for(int i=0; i<cbs.length; i++) {
4180 if (cbs[i].getState())
4182 attrmap.remove(attrs[i]);
4184 for(Enumeration e = attrmap.keys(); e.hasMoreElements(); )
4185 astr += e.nextElement();
4187 // Try to set on the server
4188 String rv[] = filemgr.get_text("setext.cgi?file="+
4189 filemgr.urlize(file.path)+"&attrs="+astr);
4190 if (rv[0].length() > 0)
4191 new ErrorWindow(filemgr.text("ext_efailed",
4196 else if (b == cancel) {
4202 class MountWindow extends FixedFrame implements CbButtonCallback
4205 FileManager filemgr;
4209 MountWindow(FileManager filemgr, FileSystem fs, RemoteFile file)
4212 setTitle(filemgr.text(fs.mtab ? "mount_title2" : "mount_title1"));
4213 this.filemgr = filemgr;
4218 setLayout(new BorderLayout());
4219 Panel cen = new BorderPanel(1, Util.body);
4220 cen.setLayout(new GridLayout(1, 1));
4221 String rusure = fs.mtab ? "mount_rusure2" : "mount_rusure1";
4222 cen.add(new Label(filemgr.text(rusure, fs.mount, fs.dev)));
4224 Panel bot = new Panel();
4225 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
4226 bot.add(yes = new CbButton(filemgr.text("yes"), this));
4227 bot.add(no = new CbButton(filemgr.text("no"), this));
4231 Util.recursiveBody(this);
4234 public void click(CbButton b)
4237 // Go ahread and do it!
4238 String rv[] = filemgr.get_text("mount.cgi?dir="+
4239 filemgr.urlize(fs.mount));
4241 if (rv[0].equals("")) {
4242 // It worked - refresh this directory and the mount list
4243 filemgr.get_filesystems();
4244 FileNode d = (FileNode)filemgr.nodemap.get(file);
4252 filemgr.show_files(file.directory);
4254 filemgr.show_files(filemgr.showing_files);
4257 // Failed - show the error
4258 new ErrorWindow(filemgr.text(
4259 fs.mtab ? "mount_err2" : "mount_err1",
4264 // Just close the window
4270 // A label that is limited to a maximum number of characters wide
4271 class MultiLabel extends BorderPanel
4273 public MultiLabel(String s, int max)
4278 public MultiLabel(String s, int max, int b)
4280 this(s, max, b, Label.CENTER);
4284 public MultiLabel(String s, int max, int b, int align)
4286 super(b, Util.body);
4287 Vector v = new Vector();
4288 StringTokenizer tok = new StringTokenizer(s.trim(), " \t");
4290 while(tok.hasMoreTokens()) {
4291 String w = tok.nextToken();
4292 line = (line == null ? w : line+" "+w);
4293 if (line.length() > max || !tok.hasMoreTokens()) {
4298 setLayout(new GridLayout(v.size(), 1, 0, 0));
4299 for(int i=0; i<v.size(); i++) {
4300 Label l = new Label((String)v.elementAt(i), Label.CENTER);
4306 // A window for choosing the format in which a directory will be downloaded
4307 class DownloadDirWindow extends FixedFrame implements CbButtonCallback
4309 CbButton zip, tgz, tar, cancel;
4310 FileManager filemgr;
4313 DownloadDirWindow(FileManager filemgr, RemoteFile file)
4316 setTitle(filemgr.text("ddir_title"));
4317 this.filemgr = filemgr;
4321 setLayout(new BorderLayout());
4322 Panel cen = new BorderPanel(1, Util.body);
4323 cen.setLayout(new GridLayout(1, 1));
4324 cen.add(new Label(filemgr.text("ddir_rusure", file.path)));
4327 Panel bot = new Panel();
4328 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
4329 bot.add(zip = new CbButton(filemgr.text("ddir_zip"), this));
4330 bot.add(tgz = new CbButton(filemgr.text("ddir_tgz"), this));
4331 bot.add(tar = new CbButton(filemgr.text("ddir_tar"), this));
4332 bot.add(cancel = new CbButton(filemgr.text("cancel"), this));
4336 Util.recursiveBody(this);
4339 public void click(CbButton b)
4342 // just close the window
4346 // open the download window
4347 int format = b == zip ? 1 :
4350 filemgr.open_file_window(file, true, format);
4355 class PreviewWindow extends Frame implements CbButtonCallback
4359 FileManager filemgr;
4362 // Previewing a file
4363 public PreviewWindow(FileManager p, RemoteFile f)
4366 file = f; filemgr = p;
4368 setTitle(filemgr.text("preview_title", file.path));
4372 URL u = new URL(filemgr.getDocumentBase(),
4373 "preview.cgi"+filemgr.urlize(file.path)+
4374 "?rand="+System.currentTimeMillis()+
4375 "&trust="+filemgr.trust+
4377 URLConnection uc = u.openConnection();
4378 filemgr.set_cookie(uc);
4379 int len = uc.getContentLength();
4380 InputStream is = uc.getInputStream();
4384 buf = new byte[uc.getContentLength()];
4386 while(got < buf.length)
4387 got += is.read(buf, got, buf.length-got);
4390 // Length is unknown .. read till the end
4393 byte data[] = new byte[16384];
4395 try { got = is.read(data); }
4396 catch(EOFException ex) { break; }
4397 if (got <= 0) break;
4398 byte nbuf[] = new byte[buf.length + got];
4399 System.arraycopy(buf, 0, nbuf, 0, buf.length);
4400 System.arraycopy(data, 0, nbuf, buf.length, got);
4405 // Check if this is really an error
4406 if (uc.getContentType().equals("text/plain")) {
4407 String s = new String(buf, 0);
4414 Image img = Toolkit.getDefaultToolkit().createImage(buf);
4415 MediaTracker waiter = new MediaTracker(this);
4416 waiter.addImage(img, 666);
4417 try { waiter.waitForAll(); }
4418 catch(InterruptedException e) { }
4419 if (img.getWidth(this) <= 0) {
4420 new ErrorWindow(filemgr.text("preview_bad"));
4429 catch(Exception e) { e.printStackTrace(); }
4434 setLayout(new BorderLayout());
4436 // Image viewing area
4437 BorderPanel mid = new BorderPanel(2, Util.body);
4438 mid.setLayout(new BorderLayout());
4439 ip = new ImagePanel(null);
4440 mid.add("Center", ip);
4444 Panel bot = new Panel();
4445 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
4446 bot.add(close_b = new CbButton(filemgr.get_image("cancel.gif"),
4447 filemgr.text("close"),
4448 CbButton.LEFT, this));
4450 Util.recursiveBody(this);
4453 public void click(CbButton b)
4462 class ImagePanel extends Panel
4466 public ImagePanel(Image img)
4471 public void paint(Graphics g)
4474 g.drawImage(img, 0, 0, this);
4478 public void setImage(Image img)
4484 public Dimension minimumSize()
4486 return new Dimension(img.getWidth(this), img.getHeight(this));
4489 public Dimension preferredSize()
4491 return minimumSize();
4495 class ExtractWindow extends FixedFrame implements CbButtonCallback
4497 CbButton yes, yesdelete, no, show;
4498 FileManager filemgr;
4501 ExtractWindow(FileManager filemgr, RemoteFile file)
4504 setTitle(filemgr.text("extract_title"));
4505 this.filemgr = filemgr;
4509 setLayout(new BorderLayout());
4510 Panel cen = new BorderPanel(1, Util.body);
4511 cen.setLayout(new GridLayout(3, 1));
4512 cen.add(new Label(filemgr.text("extract_rusure")));
4513 cen.add(new Label(file.path));
4514 cen.add(new Label(filemgr.text("extract_rusure2")));
4516 Panel bot = new Panel();
4517 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
4518 bot.add(yes = new CbButton(filemgr.text("yes"), this));
4519 bot.add(yesdelete = new CbButton(filemgr.text("extract_yes"), this));
4520 bot.add(no = new CbButton(filemgr.text("no"), this));
4521 bot.add(show = new CbButton(filemgr.text("extract_show"), this));
4525 Util.recursiveBody(this);
4528 public void click(CbButton b)
4530 if (b == yes || b == yesdelete) {
4531 // Go ahread and do it!
4532 String rv[] = filemgr.get_text("extract.cgi?file="+
4533 filemgr.urlize(file.path)+
4534 "&delete="+(b == yesdelete ? 1 : 0));
4536 if (rv[0].equals("")) {
4537 // It worked - refresh the directory
4538 RemoteFile par = file.directory;
4539 FileNode d = (FileNode)filemgr.nodemap.get(par);
4546 filemgr.show_files(filemgr.showing_files);
4549 // Failed - show the error
4550 new ErrorWindow(filemgr.text("extract_err", rv[0]));
4553 else if (b == show) {
4554 // Open window just showing contents
4555 String rv[] = filemgr.get_text("contents.cgi?file="+
4556 filemgr.urlize(file.path));
4558 if (rv[0].equals("")) {
4559 // Worked - show the files
4560 new ContentsWindow(file, filemgr, rv);
4563 // Failed - show the error
4564 new ErrorWindow(filemgr.text("extract_err2", rv[0]));
4568 // Just close the window
4574 class ContentsWindow extends FixedFrame implements CbButtonCallback
4577 FileManager filemgr;
4580 ContentsWindow(RemoteFile f, FileManager p, String rv[])
4587 setLayout(new BorderLayout());
4588 Panel bot = new Panel();
4589 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
4590 bot.add(close_b = new CbButton(filemgr.get_image("cancel.gif"),
4591 filemgr.text("close"),
4592 CbButton.LEFT, this));
4595 // Create text area showing contents
4597 for(int i=1; i<rv.length; i++) {
4598 lines = lines + rv[i] + "\n";
4600 TextArea contents = new TextArea(lines, 30, 60);
4601 contents.setEditable(false);
4602 add("Center", contents);
4603 add("North", new Label(filemgr.text("extract_shown")));
4605 Util.recursiveBody(this);
4610 public void click(CbButton b)