6 import netscape.javascript.JSObject;
8 // A java filemanager that allows the user to manipulate files on the
9 // Webmin server. Layout is similar to the windows explorer - directory
10 // tree on the left, files on the right, action buttons on the top.
11 public class FileManager extends Applet
12 implements CbButtonCallback, HierarchyCallback, MultiColumnCallback
15 CbButton ret_b, down_b, edit_b, refresh_b, props_b,
16 copy_b, cut_b, paste_b, delete_b, new_b, upload_b, mkdir_b,
17 makelink_b, rename_b, share_b, search_b, acl_b, attr_b, ext_b;
22 Hashtable nodemap = new Hashtable();
27 RemoteFile showing_files;
28 RemoteFile showing_list[];
30 // Copying and pasting
31 RemoteFile cut_buffer[];
34 static final String monmap[] = { "Jan", "Feb", "Mar", "Apr",
35 "May", "Jun", "Jul", "Aug",
36 "Sep", "Oct", "Nov", "Dec" };
38 Hashtable lang = new Hashtable();
39 Hashtable stab = new Hashtable(),
40 ntab = new Hashtable();
45 boolean got_filesystems;
46 Vector fslist = new Vector();
47 boolean read_only = false;
51 setLayout(new BorderLayout());
52 StringTokenizer tok = new StringTokenizer(getParameter("root"), " ");
53 accroot = new String[tok.countTokens()];
54 for(int i=0; tok.hasMoreTokens(); i++)
55 accroot[i] = tok.nextToken();
56 trust = getParameter("trust");
58 // download language strings
59 String l[] = get_text("lang.cgi");
60 for(int i=0; i<l.length; i++) {
61 int eq = l[i].indexOf('=');
63 lang.put(l[i].substring(0, eq), l[i].substring(eq+1));
66 // list samba file shares
67 String s[] = get_text("list_shares.cgi");
68 if (s[0].equals("1")) {
69 for(int i=1; i<s.length; i++) {
70 SambaShare ss = new SambaShare(s[i]);
71 stab.put(ss.path, ss);
77 String e[] = get_text("list_exports.cgi");
78 nfsmode = e.length == 0 ? 0 : Integer.parseInt(e[0]);
80 for(int i=1; i<e.length; i++) {
83 LinuxExport le = new LinuxExport(e[i]);
84 ntab.put(le.path, le);
86 else if (nfsmode == 2) {
88 DFSAdminExport de = new DFSAdminExport(e[i]);
89 ntab.put(de.path, de);
95 String f[] = get_text("filesystems.cgi");
96 got_filesystems = f[0].equals("1");
97 boolean acl_support = false,
100 if (got_filesystems) {
101 for(int i=1; i<f.length; i++) {
102 FileSystem fs = new FileSystem(f[i]);
103 fslist.addElement(fs);
104 if (fs.acls) acl_support = true;
105 if (fs.attrs) attr_support = true;
106 if (fs.ext) ext_support = true;
110 // get read-only flag
111 if (getParameter("ro").equals("1"))
114 // create button panel
115 BorderPanel top = new BorderPanel(2);
116 top.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
118 Panel top1 = new Panel();
119 top1.setLayout(new GridLayout(1, 0));
120 if (getParameter("return") != null)
121 top1.add(ret_b = make_button("ret.gif", text("top_ret")));
122 top1.add(down_b = make_button("down.gif", text("top_down")));
124 top1.add(edit_b = make_button("edit.gif", text("top_edit")));
125 top1.add(refresh_b = make_button("refresh.gif", text("top_refresh")));
127 top1.add(props_b = make_button("props.gif", text("top_info")));
128 if (acl_support && !read_only)
129 top1.add(acl_b = make_button("acl.gif", text("top_eacl")));
130 if (attr_support && !read_only)
131 top1.add(attr_b = make_button("attr.gif", text("top_attr")));
132 if (ext_support && !read_only)
133 top1.add(ext_b = make_button("ext.gif", text("top_ext")));
134 top1.add(search_b = make_button("search.gif", text("top_search")));
136 top.add(new Label(""));
139 Panel top2 = new Panel();
140 top2.setLayout(new GridLayout(1, 0));
141 top2.add(delete_b = make_button("cancel.gif",
142 text("top_delete")));
143 top2.add(new_b = make_button("new.gif", text("top_new")));
144 top2.add(upload_b = make_button("upload.gif",
145 text("top_upload")));
146 top2.add(mkdir_b = make_button("mkdir.gif", text("top_new")));
147 if (!getParameter("follow").equals("1"))
148 top2.add(makelink_b = make_button("makelink.gif",
150 top2.add(rename_b = make_button("rename.gif",
151 text("top_rename")));
152 if ((sambamode || nfsmode != 0) &&
153 getParameter("sharing").equals("1"))
154 top2.add(share_b = make_button("share.gif",
157 top.add(new Label(""));
159 Panel top3 = new Panel();
160 top3.setLayout(new GridLayout(1, 0));
161 top3.add(copy_b = make_button("copy.gif", text("top_copy")));
162 top3.add(cut_b = make_button("cut.gif", text("top_cut")));
163 top3.add(paste_b = make_button("paste.gif", text("top_paste")));
168 // create directory tree
169 BorderPanel left = new BorderPanel(2);
170 left.setLayout(new BorderLayout());
171 root = new FileNode(new RemoteFile(this, get_text("root.cgi")[0],null));
172 left.add("Center", dirs = new Hierarchy(root, this));
173 root.open = true; root.fill();
175 // create file window
176 BorderPanel right = new BorderPanel(2);
177 right.setLayout(new BorderLayout());
178 right.add("North", pathname = new TextField());
179 //pathname.setFont(new Font("courier", Font.PLAIN, 8));
180 String cols[] = { "", text("right_name"), text("right_size"),
181 text("right_user"), text("right_group"),
182 text("right_date") };
183 float widths[] = { .07f, .33f, .15f, .15f, .15f, .15f };
184 right.add("Center", files = new MultiColumn(cols, this));
185 files.setWidths(widths);
186 files.setDrawLines(false);
187 files.setMultiSelect(true);
188 show_files(root.file);
190 ResizePanel mid = new ResizePanel(left, right, .3, false);
193 // Go to the restricted directory
194 String home = getParameter("home");
195 String go = getParameter("goto");
196 String open = getParameter("open");
198 find_directory(open, true);
200 elsif (go != null && go.equals("1")) {
202 find_directory(home, true);
203 else if (!accroot[0].equals("/"))
204 find_directory(accroot[0], true);
208 CbButton make_button(String f, String t)
210 if (size().width < 700 && size().width > 1)
211 return new CbButton(get_image(f), this);
213 return new CbButton(get_image(f), t, CbButton.ABOVE, this);
216 // Gets an image from the images directory
217 Image get_image(String img)
219 return getImage(getDocumentBase(), "images/"+img);
222 String[] get_text(String url)
225 long now = System.currentTimeMillis();
226 if (url.indexOf('?') > 0) url += "&rand="+now;
227 else url += "?rand="+now;
228 url += "&trust="+trust;
229 URL u = new URL(getDocumentBase(), url);
230 Vector lv = new Vector();
231 LineInputStream is = new LineInputStream(u.openStream());
233 try { lv.addElement(is.gets()); }
234 catch(EOFException eof) { break; }
236 String rv[] = new String[lv.size()];
243 String err[] = { e.getMessage() };
248 // Fill the multicolumn list with files from some directory
249 boolean show_files(RemoteFile f)
251 RemoteFile fl[] = f.list();
252 if (fl == null) return false;
254 Object rows[][] = new Object[fl.length+1][];
255 long now = System.currentTimeMillis();
257 // Sort listing by chosen column
258 if (f != showing_files) {
259 // Directory has changed .. assume sort by name
260 files.sortingArrow(1, 1);
262 else if (files.sortdir != 0) {
263 // Sort by chosen order
264 RemoteFile fls[] = new RemoteFile[fl.length];
265 System.arraycopy(fl, 0, fls, 0, fl.length);
266 QuickSort.sort(fls, files.sortcol, files.sortdir);
270 // Create parent directory row
271 rows[0] = new Object[6];
272 rows[0][0] = get_image("dir.gif");
274 rows[0][2] = rows[0][3] = rows[0][4] = rows[0][5] = "";
277 Date n = new Date(now);
278 for(int i=0; i<fl.length; i++) {
279 Object row[] = rows[i+1] = new Object[6];
281 row[0] = get_image("sdir.gif");
283 row[0] = get_image(RemoteFile.tmap[fl[i].type]);
285 if (fl[i].size < 1000)
286 row[2] = spad(fl[i].size, 5)+" B";
287 else if (fl[i].size < 1000000)
288 row[2] = spad(fl[i].size/1000, 5)+" kB";
290 row[2] = spad(fl[i].size/1000000, 5)+" MB";
292 row[4] = fl[i].group;
293 Date d = new Date(fl[i].modified);
294 //if (now - fl[i].modified < 24*60*60*1000) {
295 if (n.getDate() == d.getDate() &&
296 n.getMonth() == d.getMonth() &&
297 n.getYear() == d.getYear()) {
299 row[5] = pad(d.getHours(),2)+":"+
300 pad(d.getMinutes(),2);
302 //else if (now - fl[i].modified < 24*60*60*365*1000) {
303 else if (n.getYear() == d.getYear()) {
305 row[5] = pad(d.getDate(),2)+"/"+
306 monmap[d.getMonth()];
310 row[5] = monmap[d.getMonth()]+"/"+
311 pad(d.getYear()%100, 2);
314 files.addItems(rows);
317 pathname.setText(f.path);
321 String pad(int n, int s)
323 String rv = String.valueOf(n);
324 while(rv.length() < s)
329 String spad(long n, int s)
331 String rv = String.valueOf(n);
332 while(rv.length() < s)
337 String trim_path(String p)
339 while(p.endsWith("/"))
340 p = p.substring(0, p.length()-1);
345 // Called when a node with children is opened
346 public void openNode(Hierarchy h, HierarchyNode n)
348 FileNode fn = (FileNode)n;
353 // Called when a node is closed
354 public void closeNode(Hierarchy h, HierarchyNode n)
359 // Called when the user clicks on a node
360 public void clickNode(Hierarchy h, HierarchyNode n)
362 FileNode fn = (FileNode)n;
363 if (showing_files != fn.file)
368 // Called when a user double-clicks on a node
369 public void doubleNode(Hierarchy h, HierarchyNode n)
373 // Called when a button is clicked
374 public void click(CbButton b)
376 int s = files.selected();
377 int ss[] = files.allSelected();
378 RemoteFile f = null, ff[] = new RemoteFile[0];
379 if (s > 0 || s == 0 && ss.length > 1) {
380 // At least one non-.. file was selected
381 boolean parentsel = false;
382 for(int i=0; i<ss.length; i++)
385 RemoteFile list[] = showing_list;
387 // need to exclude .. from selected list!
388 ff = new RemoteFile[ss.length-1];
389 for(int i=0,j=0; i<ss.length; i++)
391 ff[j++] = list[ss[i]-1];
392 f = s == 0 ? ff[0] : list[s-1];
395 // include all selected files
397 ff = new RemoteFile[ss.length];
398 for(int i=0; i<ss.length; i++)
399 ff[i] = list[ss[i]-1];
402 FileNode d = (FileNode)dirs.selected();
404 // Return to the webmin index
406 URL u = new URL(getDocumentBase(),
407 getParameter("return"));
408 getAppletContext().showDocument(u);
410 catch(Exception e) { }
412 else if (b == edit_b) {
413 // Open a window for editing the selected file
414 if (f == null) return;
415 if (f.type == 0 || f.type > 4)
416 new ErrorWindow(text("edit_enormal"));
418 new EditorWindow(f, this);
420 else if (b == down_b) {
421 // Force download of the selected file
422 if (f == null) return;
423 if (f.type == 0 || f.type > 4)
424 new ErrorWindow(text("view_enormal2"));
428 else if (b == refresh_b) {
429 // Refesh the selected directory (and thus any subdirs)
435 else if (b == props_b) {
436 // Display the properties window
437 if (f == null) return;
438 new PropertiesWindow(f, this);
440 else if (b == acl_b) {
441 // Display the ACL window (if filesystem supports them)
442 if (f == null) return;
443 FileSystem filefs = find_filesys(f);
444 if (filefs == null) return;
446 new ACLWindow(this, f);
448 new ErrorWindow(text("eacl_efs", filefs.mount));
450 else if (b == attr_b) {
451 // Display the attributes window (if filesystem supports them)
452 if (f == null) return;
453 FileSystem filefs = find_filesys(f);
454 if (filefs == null) return;
456 new AttributesWindow(this, f);
458 new ErrorWindow(text("attr_efs", filefs.mount));
460 else if (b == ext_b) {
461 // Display EXT attributes window (if filesystem supports them)
462 if (f == null) return;
463 FileSystem filefs = find_filesys(f);
464 if (filefs == null) return;
466 new EXTWindow(this, f);
468 new ErrorWindow(text("ext_efs", filefs.mount));
470 else if (b == copy_b) {
471 // Copy the selected files
472 if (f == null) return;
476 else if (b == cut_b) {
477 // Cut the selected file
478 if (f == null) return;
482 else if (b == paste_b) {
483 // Paste the copied file
484 if (cut_buffer == null) {
485 new ErrorWindow(text("paste_ecopy"));
489 // Check for existing file clashes
492 // Go through all the files to paste
493 for(int i=0; i<cut_buffer.length; i++) {
494 RemoteFile cf = cut_buffer[i];
496 // Check for an existing file
497 RemoteFile already = showing_files.find(cf.name);
498 String sp = showing_files.path;
499 String dest_path = sp.equals("/") ? sp+cf.name
501 if (already != null) {
502 // File exists .. offer to rename
503 new OverwriteWindow(this, already, cf, i);
506 // do the move or copy
507 RemoteFile nf = paste_file(cf, showing_files,
508 dest_path, null, cut_mode);
509 if (cut_mode && nf != null) {
510 // Paste from the destination path
518 else if (b == delete_b) {
519 // Delete the selected files
520 if (f == null) return;
521 new DeleteWindow(this, ff);
523 else if (b == new_b) {
524 // Open a window for creating a file
525 new EditorWindow(showing_files.path, this);
527 else if (b == upload_b) {
528 // Call javascript to open an upload window
530 JSObject win = JSObject.getWindow(this);
531 String params[] = { showing_files.path };
532 win.call("upload", params);
535 new ErrorWindow(text("upload_efailed", e.getMessage()));
538 else if (b == mkdir_b) {
539 // Prompt for new directory
540 new MkdirWindow(showing_files.path, this);
542 else if (b == makelink_b) {
543 // Prompt for a new symlink
544 new LinkWindow(showing_files.path, this);
546 else if (b == rename_b) {
547 // Prompt for new filename
548 if (f == null) return;
549 new RenameWindow(this, f);
551 else if (b == share_b) {
552 // Open a window for editing sharing options
553 if (f == null || f.type != RemoteFile.DIR) return;
554 new SharingWindow(f, this);
556 else if (b == search_b) {
557 // Open window for finding a file
558 new SearchWindow(showing_files.path, this);
562 // Returns the object for some directory, or null if not found.
563 RemoteFile find_directory(String p, boolean fill)
567 for(int r=0; r<accroot.length; r++) {
568 int rl = accroot[r].length();
569 if (accroot[r].equals("/"))
571 else if (l >= rl && p.substring(0, rl).equals(accroot[r]))
573 else if (l < rl && accroot[r].substring(0, l).equals(p))
577 new ErrorWindow(text("find_eaccess", p));
580 FileNode posnode = root;
581 RemoteFile pos = posnode.file;
582 StringTokenizer tok = new StringTokenizer(p, "/");
583 while(tok.hasMoreTokens()) {
584 String fn = tok.nextToken();
585 if (fn.equals("")) continue;
586 RemoteFile fl[] = pos.list();
587 if (fl == null) return null;
592 boolean found = false;
593 for(int i=0; i<fl.length; i++)
594 if (fl[i].name.equals(fn)) {
599 new ErrorWindow(text("find_eexist", fn, p));
603 new ErrorWindow(text("find_edir", fn, p));
607 posnode = (FileNode)nodemap.get(pos);
610 if (show_files(pos)) {
613 dirs.select(posnode);
620 FileSystem find_filesys(RemoteFile f)
622 FileSystem filefs = null;
623 for(int i=0; i<fslist.size(); i++) {
624 FileSystem fs = (FileSystem)fslist.elementAt(i);
625 int l = fs.mount.length();
626 if (fs.mount.equals(f.path) ||
627 (f.path.length() >= l+1 &&
628 f.path.substring(0, l+1).equals(fs.mount+"/")) ||
629 fs.mount.equals("/")) {
636 public boolean action(Event e, Object o)
638 if (e.target == pathname) {
639 // A new path was entered.. cd to it
640 String p = pathname.getText().trim();
641 if (p.equals("")) return true;
642 find_directory(p, true);
649 // Called on a single click on a list item
650 public void singleClick(MultiColumn list, int num)
655 // Called upon double-clicking on a list item
656 public void doubleClick(MultiColumn list, int num)
659 // Go to parent directory
660 if (showing_files.directory != null) {
661 ((FileNode)nodemap.get(showing_files)).open = false;
662 show_files(showing_files.directory);
663 dirs.select((FileNode)nodemap.get(showing_files));
668 RemoteFile d = showing_list[num-1];
670 // Open this directory
671 FileNode pn = (FileNode)nodemap.get(showing_files);
674 FileNode fn = (FileNode)nodemap.get(d);
682 else if (d.type <= 4) {
683 // Direct the browser to this file
684 show_file(d, list.last_event.shiftDown());
688 // Called when the user clicks on a column heading so that it can
690 public void headingClicked(MultiColumn list, int col)
693 return; // ignore click on icon column?
694 if (col == list.sortcol) {
695 list.sortingArrow(col, list.sortdir == 2 ? 1 : 2);
698 list.sortingArrow(col, 1);
701 // Re-show the list in the new order, but with the same files selected
702 int ss[] = files.allSelected();
703 RemoteFile ssf[] = new RemoteFile[ss.length];
704 for(int i=0; i<ss.length; i++)
705 ssf[i] = showing_list[ss[i]-1];
706 show_files(showing_files);
707 for(int i=0; i<ss.length; i++) {
708 for(int j=0; j<showing_list.length; j++) {
709 if (showing_list[j] == ssf[i]) {
718 void show_file(RemoteFile f, boolean download)
722 URL u = new URL(getDocumentBase(),
723 "show.cgi"+urlize(f.path)+
724 "?rand="+System.currentTimeMillis()+
725 "&type=application%2Funknown"+
727 getAppletContext().showDocument(u);
730 URL u = new URL(getDocumentBase(),
731 "show.cgi"+urlize(f.path)+
732 "?rand="+System.currentTimeMillis()+
734 getAppletContext().showDocument(u, "show");
737 catch(Exception e) { }
740 static String urlize(String s)
742 StringBuffer rv = new StringBuffer();
743 for(int i=0; i<s.length(); i++) {
744 char c = s.charAt(i);
746 rv.append("%0"+Integer.toString(c, 16));
747 else if (!Character.isLetterOrDigit(c) && c != '/' &&
748 c != '.' && c != '_' && c != '-')
749 rv.append("%"+Integer.toString(c, 16));
753 return rv.toString();
756 static String un_urlize(String s)
758 StringBuffer rv = new StringBuffer();
759 for(int i=0; i<s.length(); i++) {
760 char c = s.charAt(i);
762 rv.append((char)Integer.parseInt(
763 s.substring(i+1, i+3), 16));
769 return rv.toString();
772 public void upload_notify(String path_str, String info)
774 int sl = path_str.lastIndexOf('/');
775 String par_str = path_str.substring(0, sl),
776 file_str = path_str.substring(sl+1);
777 RemoteFile par = find_directory(par_str, false);
778 RemoteFile upfile = par.find(file_str);
779 if (upfile == null) {
780 upfile = new RemoteFile(this, info, par);
783 show_files(showing_files);
786 public String text(String k, String p[])
788 String rv = (String)lang.get(k);
789 if (rv == null) rv = "???";
790 for(int i=0; i<p.length; i++) {
791 int idx = rv.indexOf("$"+(i+1));
793 rv = rv.substring(0, idx)+p[i]+rv.substring(idx+2);
798 public String text(String k)
804 public String text(String k, String p1)
810 public String text(String k, String p1, String p2)
812 String p[] = { p1, p2 };
816 RemoteFile paste_file(RemoteFile src, RemoteFile dir,
817 String dest, RemoteFile already, boolean mode)
819 // Move or copy the actual file
820 String[] rv = get_text((mode ? "move.cgi" : "copy.cgi")+
821 "?from="+urlize(src.path)+
822 "&to="+urlize(dest));
823 if (rv[0].length() > 0) {
824 new ErrorWindow(text(
825 mode ? "paste_emfailed" : "paste_ecfailed", rv[0]));
828 RemoteFile file = new RemoteFile(this, rv[1], dir);
829 if (already == null) {
830 // Add to the parent directory
834 // Update the existing file
835 already.type = file.type;
836 already.user = file.user;
837 already.group = file.group;
838 already.size = file.size;
839 already.perms = file.perms;
840 already.modified = file.modified;
844 // Delete the old file
845 src.directory.delete(src);
848 // Moving or copying a directory.. update the tree
849 FileNode dest_par_node =
850 (FileNode)nodemap.get(showing_files);
851 dest_par_node.add(new FileNode(file));
853 FileNode cut_par_node =
854 (FileNode)nodemap.get(src.directory);
855 FileNode cut_file_node =
856 (FileNode)nodemap.get(src);
857 if (cut_par_node != null &&
858 cut_file_node != null)
859 cut_par_node.ch.removeElement(
864 show_files(showing_files);
869 // A node in the directory tree
870 class FileNode extends HierarchyNode
876 FileNode(RemoteFile file)
879 parent = file.parent;
880 im = parent.get_image(file.shared() ? "sdir.gif" : "dir.gif");
883 parent.nodemap.put(file, this);
886 // Create the nodes for subdirectories
890 RemoteFile l[] = file.list();
891 if (l == null) return;
892 ch.removeAllElements();
893 for(int i=0; i<l.length; i++)
895 ch.addElement(new FileNode(l[i]));
896 parent.dirs.redraw();
903 for(int i=0; i<=ch.size(); i++) {
904 FileNode ni = i==ch.size() ? null : (FileNode)ch.elementAt(i);
905 if (ni == null || ni.text.compareTo(n.text) > 0) {
906 ch.insertElementAt(n, i);
916 static final int DIR = 0;
917 static final int TEXT = 1;
918 static final int IMAGE = 2;
919 static final int BINARY = 3;
920 static final int UNKNOWN = 4;
921 static final int SYMLINK = 5;
922 static final int DEVICE = 6;
923 static final int PIPE = 7;
924 static final String[] tmap = { "dir.gif", "text.gif", "image.gif",
925 "binary.gif", "unknown.gif",
926 "symlink.gif", "device.gif",
938 RemoteFile directory;
940 // Parse a line of text to a file object
941 RemoteFile(FileManager parent, String line, RemoteFile d)
943 this.parent = parent;
944 StringTokenizer tok = new StringTokenizer(line, "\t");
945 path = tok.nextToken();
946 type = Integer.parseInt(tok.nextToken());
947 user = tok.nextToken();
948 group = tok.nextToken();
949 size = Long.parseLong(tok.nextToken());
950 perms = Integer.parseInt(tok.nextToken());
951 modified = Long.parseLong(tok.nextToken())*1000;
952 if (type == 5) linkto = tok.nextToken();
954 if (path.equals("/")) name = "/";
955 else name = path.substring(path.lastIndexOf('/')+1);
958 // Create a new, empty file object
961 // Returns a list of files in this directory
965 String l[] = parent.get_text("list.cgi?dir="+
966 parent.urlize(path));
967 if (l[0].length() > 0) {
968 //list = new RemoteFile[0];
969 // Error reading the remote directory!
970 new ErrorWindow(parent.text("list_edir", path, l[0]));
974 list = new RemoteFile[l.length-3];
975 for(int i=3; i<l.length; i++)
976 list[i-3] = new RemoteFile(parent, l[i], this);
982 RemoteFile find(String n)
984 RemoteFile l[] = list();
986 for(int i=0; i<l.length; i++)
987 if (l[i].name.equals(n))
993 void add(RemoteFile f)
995 RemoteFile nlist[] = new RemoteFile[list.length+1];
997 for(int i=0; i<list.length; i++) {
998 if (list[i].name.compareTo(f.name) > 0 && offset == 0) {
1002 nlist[i+offset] = list[i];
1004 if (offset == 0) nlist[list.length] = f;
1008 void delete(RemoteFile f)
1010 RemoteFile nlist[] = new RemoteFile[list.length-1];
1011 for(int i=0,j=0; i<list.length; i++)
1013 nlist[j++] = list[i];
1019 return type == DIR &&
1020 (parent.stab.get(path) != null ||
1021 parent.ntab.get(path) != null);
1025 class EditorWindow extends FixedFrame implements CbButtonCallback
1029 CbButton save_b, cancel_b, goto_b, find_b;
1031 FileManager filemgr;
1032 GotoWindow goto_window;
1033 FindReplaceWindow find_window;
1035 // Editing an existing file
1036 EditorWindow(RemoteFile f, FileManager p)
1039 file = f; filemgr = p;
1041 setTitle(filemgr.text("edit_title", file.path));
1045 URL u = new URL(filemgr.getDocumentBase(),
1046 "show.cgi"+filemgr.urlize(file.path)+
1047 "?rand="+System.currentTimeMillis()+
1048 "&trust="+filemgr.trust+"&edit=1");
1049 URLConnection uc = u.openConnection();
1050 int len = uc.getContentLength();
1051 InputStream is = uc.getInputStream();
1055 buf = new byte[uc.getContentLength()];
1057 while(got < buf.length)
1058 got += is.read(buf, got, buf.length-got);
1061 // Length is unknown .. read till the end
1064 byte data[] = new byte[16384];
1066 try { got = is.read(data); }
1067 catch(EOFException ex) { break; }
1068 if (got <= 0) break;
1069 byte nbuf[] = new byte[buf.length + got];
1070 System.arraycopy(buf, 0, nbuf, 0, buf.length);
1071 System.arraycopy(data, 0, nbuf, buf.length, got);
1075 edit.setText(new String(buf, 0));
1077 file.size = buf.length;
1079 catch(Exception e) { e.printStackTrace(); }
1082 // Creating a new file
1083 EditorWindow(String f, FileManager p)
1088 setTitle(filemgr.text("edit_title2"));
1089 name.setText(f.equals("/") ? f : f+"/");
1090 name.select(name.getText().length(), name.getText().length());
1093 void makeUI(boolean add_name)
1095 setLayout(new BorderLayout());
1097 Panel np = new Panel();
1098 np.setLayout(new BorderLayout());
1099 np.add("West", new Label(filemgr.text("edit_filename")));
1100 np.add("Center", name = new TextField());
1103 add("Center", edit = new TextArea(20, 80));
1104 edit.setFont(new Font("courier", Font.PLAIN, 14));
1105 Panel bot = new Panel();
1106 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1107 bot.add(goto_b = new CbButton(filemgr.get_image("goto.gif"),
1108 filemgr.text("edit_goto"),
1109 CbButton.LEFT, this));
1110 bot.add(find_b = new CbButton(filemgr.get_image("find.gif"),
1111 filemgr.text("edit_find"),
1112 CbButton.LEFT, this));
1113 bot.add(new Label(" "));
1114 bot.add(save_b = new CbButton(filemgr.get_image("save.gif"),
1115 filemgr.text("save"),
1116 CbButton.LEFT, this));
1117 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1118 filemgr.text("cancel"),
1119 CbButton.LEFT, this));
1125 public void click(CbButton b)
1128 RemoteFile par = null, already = null;
1131 // Locate the filemgr directory
1132 save_path = filemgr.trim_path(name.getText());
1133 int sl = save_path.lastIndexOf('/');
1134 par = filemgr.find_directory(
1135 save_path.substring(0, sl), false);
1136 if (par == null) return;
1137 already = par.find(save_path.substring(sl+1));
1138 if (already != null &&
1139 (already.type == 0 || already.type == 5)) {
1141 filemgr.text("edit_eover", save_path));
1145 else save_path = file.path;
1147 // Save the file back again
1148 String s = edit.getText(), line;
1150 URL u = new URL(filemgr.getDocumentBase(),
1151 "save.cgi"+filemgr.urlize(save_path)+
1152 "?rand="+System.currentTimeMillis()+
1153 "&trust="+filemgr.trust);
1154 URLConnection uc = u.openConnection();
1155 uc.setDoOutput(true);
1156 OutputStream os = uc.getOutputStream();
1157 byte buf[] = new byte[s.length()];
1158 s.getBytes(0, buf.length, buf, 0);
1161 LineInputStream is = new LineInputStream(
1162 uc.getInputStream());
1163 String err = is.gets();
1164 if (err.length() > 0) {
1166 filemgr.text("edit_esave", err));
1173 catch(Exception e) { e.printStackTrace(); return; }
1176 // Create and insert or replace the file object
1177 file = new RemoteFile(filemgr, line, par);
1178 if (already != null) {
1179 // A file with this name exists
1180 already.type = file.type;
1181 already.user = file.user;
1182 already.group = file.group;
1183 already.size = file.size;
1184 already.perms = file.perms;
1185 already.modified = file.modified;
1193 file.size = s.length();
1194 file.modified = System.currentTimeMillis();
1196 filemgr.show_files(filemgr.showing_files);
1199 else if (b == cancel_b) {
1203 else if (b == goto_b) {
1204 // Open a dialog asking which line to go to
1205 if (goto_window != null)
1206 goto_window.toFront();
1208 goto_window = new GotoWindow(this);
1210 else if (b == find_b) {
1211 // Open the search (and replace) dialog
1212 if (find_window != null)
1213 find_window.toFront();
1215 find_window = new FindReplaceWindow(this);
1219 public void dispose()
1222 if (goto_window != null) goto_window.dispose();
1223 if (find_window != null) find_window.dispose();
1227 class GotoWindow extends FixedFrame implements CbButtonCallback
1229 EditorWindow editor;
1230 FileManager filemgr;
1232 CbButton goto_b, cancel_b;
1234 GotoWindow(EditorWindow e)
1237 filemgr = e.filemgr;
1239 setLayout(new BorderLayout());
1240 add("West", new Label(filemgr.text("edit_gotoline")));
1241 add("Center", line = new TextField(10));
1242 Panel bot = new Panel();
1243 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1244 bot.add(goto_b = new CbButton(filemgr.get_image("goto.gif"),
1245 filemgr.text("edit_goto"),
1246 CbButton.LEFT, this));
1247 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1248 filemgr.text("close"),
1249 CbButton.LEFT, this));
1255 public void click(CbButton b)
1258 // Go to the chose line, if it exists
1260 try { lnum = Integer.parseInt(line.getText()); }
1261 catch(Exception e) { return; }
1263 String txt = editor.edit.getText();
1265 for(c=0; c<txt.length(); c++) {
1266 if (txt.charAt(c) == '\n') {
1270 editor.edit.select(c, c);
1277 else if (b == cancel_b) {
1278 // Just close the window
1283 public void dispose()
1286 editor.goto_window = null;
1289 public boolean handleEvent(Event e)
1291 if (e.target == line && e.id == Event.KEY_RELEASE && e.key == 10) {
1299 class FindReplaceWindow extends FixedFrame implements CbButtonCallback
1301 EditorWindow editor;
1302 FileManager filemgr;
1303 TextField find, replace;
1304 CbButton find_b, replace_b, all_b, cancel_b;
1306 FindReplaceWindow(EditorWindow e)
1309 filemgr = e.filemgr;
1310 setLayout(new BorderLayout());
1312 Panel left = new Panel();
1313 left.setLayout(new GridLayout(2, 1));
1314 left.add(new Label(filemgr.text("edit_searchfor")));
1315 left.add(new Label(filemgr.text("edit_replaceby")));
1318 Panel right = new Panel();
1319 right.setLayout(new GridLayout(2, 1));
1320 right.add(find = new TextField(40));
1321 right.add(replace = new TextField(40));
1322 add("Center", right);
1324 Panel bot = new Panel();
1325 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1326 bot.add(find_b = new CbButton(filemgr.get_image("find.gif"),
1327 filemgr.text("edit_find"),
1328 CbButton.LEFT, this));
1329 bot.add(replace_b = new CbButton(filemgr.get_image("replace.gif"),
1330 filemgr.text("edit_replace"),
1331 CbButton.LEFT, this));
1332 bot.add(all_b = new CbButton(filemgr.get_image("all.gif"),
1333 filemgr.text("edit_all"),
1334 CbButton.LEFT, this));
1335 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1336 filemgr.text("close"),
1337 CbButton.LEFT, this));
1343 public void click(CbButton b)
1345 String findtxt = find.getText();
1346 String edittxt = editor.edit.getText();
1347 if (findtxt.length() == 0)
1350 // Find the next occurrance of the text, starting from
1351 // the cursor + 1, and select it
1352 int pos = edittxt.indexOf(findtxt,
1353 editor.edit.getSelectionStart()+1);
1355 new ErrorWindow(filemgr.text("edit_notfound", findtxt));
1357 editor.edit.select(pos, pos+findtxt.length());
1359 else if (b == replace_b) {
1360 // If the word to search for is selected, replace it. Otherwise
1361 // just search for the next one
1362 int st = editor.edit.getSelectionStart(),
1363 en = editor.edit.getSelectionEnd();
1365 String sel = edittxt.substring(st, en);
1366 if (sel.equals(findtxt)) {
1367 // Replace the selected
1368 editor.edit.setText(edittxt.substring(0, st)+
1370 edittxt.substring(en));
1371 editor.edit.select(st, st);
1377 else if (b == all_b) {
1378 // Replace all occurrances of the text in the editor
1380 int len = findtxt.length();
1381 int st = editor.edit.getSelectionStart(),
1382 en = editor.edit.getSelectionEnd();
1383 while((pos = edittxt.indexOf(findtxt, pos)) != -1) {
1384 edittxt = edittxt.substring(0, pos)+
1386 edittxt.substring(pos+len);
1389 editor.edit.setText(edittxt);
1390 editor.edit.select(st, en); // put back old selection
1392 else if (b == cancel_b) {
1393 // Just close the window
1398 public void dispose()
1401 editor.find_window = null;
1405 class PropertiesWindow extends FixedFrame implements CbButtonCallback
1408 FileManager filemgr;
1409 CbButton save_b, cancel_b;
1412 TextField user, group;
1413 Checkbox setuid, setgid;
1414 PermissionsPanel user_p, group_p, other_p;
1419 PropertiesWindow(RemoteFile f, FileManager p)
1426 setLayout(new BorderLayout());
1427 Panel bot = new Panel();
1428 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
1429 bot.add(save_b = new CbButton(filemgr.get_image("save.gif"),
1430 filemgr.text("save"),
1431 CbButton.LEFT, this));
1432 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1433 filemgr.text("cancel"),
1434 CbButton.LEFT, this));
1437 Panel mid = new Panel();
1438 mid.setLayout(new BorderLayout());
1439 TabbedPanel tab = null;
1442 // Create file details section
1443 Panel det = new LinedPanel(filemgr.text("info_file")),
1444 dl = new Panel(), dr = new Panel();
1445 setup_leftright(det, dl, dr);
1446 add_item(filemgr.text("info_path"),
1447 new Label(file.path), dl, dr);
1448 add_item(filemgr.text("info_type"),
1449 new Label(filemgr.text("file_type"+file.type)), dl, dr);
1450 add_item(filemgr.text("info_size"),
1451 new Label(String.valueOf(file.size)),dl,dr);
1452 add_item(filemgr.text("info_mod"),
1453 new Label(String.valueOf(new Date(file.modified))), dl, dr);
1455 add_item(filemgr.text("info_link"),
1456 linkto = new TextField(file.linkto, 30), dl, dr);
1457 mid = add_panel(mid, det);
1459 // Create permissions section
1460 Panel per = new LinedPanel(filemgr.text("info_perms")),
1461 pl = new Panel(), pr = new Panel();
1462 setup_leftright(per, pl, pr);
1463 add_item(filemgr.text("info_user"),
1464 user_p = new PermissionsPanel(file, 64, filemgr), pl, pr);
1465 add_item(filemgr.text("info_group"),
1466 group_p = new PermissionsPanel(file, 8, filemgr), pl, pr);
1467 add_item(filemgr.text("info_other"),
1468 other_p = new PermissionsPanel(file, 1, filemgr), pl,pr);
1469 if (file.type == 0) {
1470 add_item(filemgr.text("info_sticky"), sticky = new Checkbox(
1471 filemgr.text("info_sticky2")), pl,pr);
1472 sticky.setState((file.perms&01000) != 0);
1474 add_item(filemgr.text("info_octal"), octal = new TextField(4), pl, pr);
1475 octal.setEditable(false);
1476 mid = add_panel(mid, per);
1478 // Create ownership section
1479 Panel own = new LinedPanel(filemgr.text("info_own")),
1480 ol = new Panel(), or = new Panel();
1481 setup_leftright(own, ol, or);
1482 add_item(filemgr.text("info_user"),
1483 user = new TextField(file.user, 10), ol, or);
1484 if (file.type != 0) {
1485 add_item(filemgr.text("info_setuid"),
1486 setuid = new Checkbox(filemgr.text("info_setuid2")),
1488 setuid.setState((file.perms & 0x800) != 0);
1490 add_item(filemgr.text("info_group"),
1491 group = new TextField(file.group, 10), ol, or);
1493 add_item(filemgr.text("info_setgid"),
1494 setgid = new Checkbox(filemgr.text("info_setgid2")), ol, or);
1496 add_item(filemgr.text("info_setgid"),
1497 setgid = new Checkbox(filemgr.text("info_setgid3")), ol, or);
1498 setgid.setState((file.perms & 0x400) != 0);
1499 mid = add_panel(mid, own);
1501 if (file.type == 0) {
1502 // Create recursion section
1503 Panel rec = new LinedPanel(filemgr.text("info_apply"));
1504 rec.setLayout(new BorderLayout());
1505 rec_mode = new Choice();
1506 for(int i=1; i<=3; i++)
1507 rec_mode.addItem(filemgr.text("info_apply"+i));
1508 rec.add("Center", rec_mode);
1509 mid = add_panel(mid, rec);
1517 Panel add_panel(Panel p, Component c)
1520 Panel np = new Panel();
1521 np.setLayout(new BorderLayout());
1522 p.add("Center", np);
1526 public void click(CbButton b)
1530 int perms = get_perms();
1533 rec = rec_mode.getSelectedIndex();
1534 String rv[] = filemgr.get_text(
1535 "chmod.cgi?path="+filemgr.urlize(file.path)+
1536 "&perms="+perms+"&user="+user.getText()+
1537 "&group="+group.getText()+"&rec="+rec+
1538 (linkto==null ? "" : "&linkto="+linkto.getText()));
1539 if (rv[0].length() > 0) {
1540 // Something went wrong
1541 new ErrorWindow(filemgr.text("info_efailed",
1545 // Update all changed file objects
1547 file.linkto = linkto.getText();
1549 update_file(file, perms, false);
1550 else if (rec == 1) {
1551 // Update files in this directory
1552 update_file(file, perms, false);
1553 recurse_files(file, perms, false);
1555 else if (rec == 2) {
1556 // Update files and subdirs
1557 update_file(file, perms, false);
1558 recurse_files(file, perms, true);
1561 // Update directory list
1562 int os = filemgr.files.selected();
1563 filemgr.show_files(filemgr.showing_files);
1564 filemgr.files.select(os);
1574 void update_file(RemoteFile f, int perms, boolean perms_only)
1576 f.user = user.getText();
1577 f.group = group.getText();
1579 f.perms = (perms & 0777) | (f.perms & 037777777000);
1584 void recurse_files(RemoteFile f, int perms, boolean do_subs)
1586 if (f.list == null) return;
1587 for(int i=0; i<f.list.length; i++) {
1588 RemoteFile ff = f.list[i];
1589 if (ff.type == 5) continue;
1590 else if (ff.type == 0) {
1592 update_file(ff, perms, false);
1593 recurse_files(ff, perms, true);
1596 else update_file(ff, perms, true);
1600 void setup_leftright(Panel m, Panel l, Panel r)
1602 m.setLayout(new BorderLayout());
1603 Panel p = new Panel();
1604 p.setLayout(new BorderLayout());
1607 l.setLayout(new GridLayout(0, 1));
1608 r.setLayout(new GridLayout(0, 1));
1612 void add_item(String t, Component c, Panel l, Panel r)
1614 l.add(new Label(t));
1615 Panel p = new Panel();
1616 p.setLayout(new BorderLayout());
1623 String oct = Integer.toOctalString(get_perms());
1624 while(oct.length() < 4)
1633 perms |= (file.perms & 0x800);
1635 perms |= (setuid.getState() ? 0x800 : 0);
1636 perms |= (setgid.getState() ? 0x400 : 0);
1637 perms |= user_p.getPerms();
1638 perms |= group_p.getPerms();
1639 perms |= other_p.getPerms();
1641 perms |= (file.perms & 01000);
1643 perms |= (sticky.getState() ? 01000 : 0);
1647 public boolean handleEvent(Event e)
1649 if (e.target instanceof Checkbox) {
1657 class PermissionsPanel extends Panel
1659 Checkbox read, write, exec;
1662 PermissionsPanel(RemoteFile file, int base, FileManager filemgr)
1664 int perms = file.perms;
1666 setLayout(new GridLayout(1, 3));
1667 add(read = new Checkbox(filemgr.text("info_read")));
1668 read.setState((perms&(base<<2)) != 0);
1669 add(write = new Checkbox(filemgr.text("info_write")));
1670 write.setState((perms&(base<<1)) != 0);
1671 add(exec = new Checkbox(
1672 filemgr.text(file.type==0 ? "info_list" : "info_exec")));
1673 exec.setState((perms&base) != 0);
1679 rv |= (read.getState() ? (base<<2) : 0);
1680 rv |= (write.getState() ? (base<<1) : 0);
1681 rv |= (exec.getState() ? base : 0);
1686 class DeleteWindow extends FixedFrame implements CbButtonCallback
1688 CbButton delete_b, cancel_b;
1689 FileManager filemgr;
1692 DeleteWindow(FileManager p, RemoteFile ff[])
1696 setTitle(filemgr.text(ff.length > 1 ? "delete_mtitle" :
1697 ff[0].type == 0 ? "delete_dtitle" :
1700 setLayout(new BorderLayout());
1701 if (ff.length > 1) {
1702 add("North", new Label(filemgr.text("delete_mdesc")));
1703 Panel mp = new Panel();
1704 mp.setLayout(new GridLayout(ff.length, 1));
1705 for(int i=0; i<ff.length; i++)
1706 mp.add(new Label(ff[i].path));
1710 add("Center", new MultiLabel(filemgr.text(
1711 ff[0].type == 0 ? "delete_ddesc" : "delete_fdesc",
1713 Panel bot = new Panel();
1714 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
1715 bot.add(delete_b = new CbButton(filemgr.get_image("save.gif"),
1716 filemgr.text("delete"),
1717 CbButton.LEFT, this));
1718 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1719 filemgr.text("cancel"),
1720 CbButton.LEFT, this));
1727 public void click(CbButton b)
1729 if (b == delete_b) {
1730 // Delete the file or directory
1731 boolean need_redraw = false, need_reshow = false;
1732 for(int i=0; i<files.length; i++) {
1733 RemoteFile file = files[i];
1734 String rv[] = filemgr.get_text("delete.cgi?file="+
1735 filemgr.urlize(file.path));
1736 if (rv[0].length() > 0) {
1737 new ErrorWindow(filemgr.text("delete_efailed",
1742 // done the deed.. update data structures
1743 RemoteFile pf = file.directory;
1745 if (filemgr.showing_files == pf) {
1746 // Need to refresh the list as well..
1750 FileNode node = (FileNode)filemgr.nodemap.get(
1752 FileNode pnode = (FileNode)filemgr.nodemap.get(
1755 // Take the directory out of the tree..
1756 pnode.ch.removeElement(node);
1761 if (need_reshow) filemgr.show_files(filemgr.showing_files);
1762 if (need_redraw) filemgr.dirs.redraw();
1765 else if (b == cancel_b)
1770 class MkdirWindow extends FixedFrame implements CbButtonCallback
1772 FileManager filemgr;
1774 CbButton create_b, cancel_b;
1776 MkdirWindow(String d, FileManager p)
1779 setTitle(filemgr.text("mkdir_title"));
1780 setLayout(new BorderLayout());
1781 add("West", new Label(filemgr.text("mkdir_dir")));
1782 add("Center", dir = new TextField(d.equals("/") ? "/" : d+"/", 40));
1783 dir.select(dir.getText().length(), dir.getText().length());
1784 Panel bot = new Panel();
1785 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
1786 bot.add(create_b = new CbButton(filemgr.get_image("save.gif"),
1787 filemgr.text("create"),
1788 CbButton.LEFT, this));
1789 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1790 filemgr.text("cancel"),
1791 CbButton.LEFT, this));
1797 public void click(CbButton b)
1799 if (b == create_b) {
1800 // Find the filemgr directory
1801 String path = dir.getText();
1802 path = filemgr.trim_path(path);
1803 int sl = path.lastIndexOf('/');
1804 RemoteFile par = filemgr.find_directory(
1805 path.substring(0, sl), false);
1806 if (par.find(path.substring(sl+1)) != null) {
1807 new ErrorWindow(filemgr.text("mkdir_eexists", path));
1810 String rv[] = filemgr.get_text("mkdir.cgi?dir="+
1811 filemgr.urlize(path));
1812 if (rv[0].length() > 0) {
1813 new ErrorWindow(filemgr.text("mkdir_efailed", rv[0]));
1816 RemoteFile file = new RemoteFile(filemgr, rv[1], par);
1818 FileNode parnode = (FileNode)filemgr.nodemap.get(par);
1819 if (parnode != null) {
1821 parnode.add(new FileNode(file));
1822 filemgr.dirs.redraw();
1824 filemgr.show_files(filemgr.showing_files);
1831 class LinkWindow extends FixedFrame implements CbButtonCallback
1833 FileManager filemgr;
1835 CbButton create_b, cancel_b;
1837 LinkWindow(String d, FileManager p)
1840 setLayout(new BorderLayout());
1841 setTitle(filemgr.text("link_title"));
1842 Panel l = new Panel(), r = new Panel();
1843 l.setLayout(new GridLayout(0, 1));
1844 l.add(new Label(filemgr.text("link_from")));
1845 l.add(new Label(filemgr.text("link_to")));
1846 r.setLayout(new GridLayout(0, 1));
1847 r.add(from = new TextField(d.equals("/") ? "/" : d+"/", 40));
1848 from.select(from.getText().length(), from.getText().length());
1849 r.add(to = new TextField());
1850 add("West", l); add("Center", r);
1851 Panel bot = new Panel();
1852 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
1853 bot.add(create_b = new CbButton(filemgr.get_image("save.gif"),
1854 filemgr.text("create"),
1855 CbButton.LEFT, this));
1856 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1857 filemgr.text("cancel"),
1858 CbButton.LEFT, this));
1864 public void click(CbButton b)
1866 if (b == create_b) {
1868 String from_str = from.getText().trim();
1869 int sl = from_str.lastIndexOf('/');
1870 String par_str = from_str.substring(0, sl),
1871 file_str = from_str.substring(sl+1);
1872 RemoteFile par = filemgr.find_directory(par_str, false);
1873 if (par == null) return;
1874 if (par.find(file_str) != null) {
1875 new ErrorWindow(filemgr.text("link_eexists", from_str));
1879 // Create the actual link
1880 String rv[] = filemgr.get_text("makelink.cgi?from="+
1881 filemgr.urlize(from_str)+"&to="+
1882 filemgr.urlize(to.getText()));
1883 if (rv[0].length() > 0) {
1884 new ErrorWindow(filemgr.text("link_efailed", rv[0]));
1887 RemoteFile file = new RemoteFile(filemgr, rv[1], par);
1889 filemgr.show_files(filemgr.showing_files);
1892 else if (b == cancel_b)
1897 class RenameWindow extends FixedFrame implements CbButtonCallback
1899 FileManager filemgr;
1901 TextField oldname, newname;
1902 CbButton rename_b, cancel_b;
1904 RenameWindow(FileManager p, RemoteFile f)
1906 filemgr = p; file = f;
1907 setLayout(new BorderLayout());
1908 setTitle(filemgr.text("rename_title", file.path));
1909 Panel l = new Panel(), r = new Panel();
1910 l.setLayout(new GridLayout(0, 1));
1911 l.add(new Label(filemgr.text("rename_old")));
1912 l.add(new Label(filemgr.text("rename_new")));
1913 r.setLayout(new GridLayout(0, 1));
1914 r.add(oldname = new TextField(file.name, 20));
1915 oldname.setEditable(false);
1916 r.add(newname = new TextField(file.name, 20));
1917 newname.select(file.name.length(), file.name.length());
1918 add("West", l); add("Center", r);
1920 Panel bot = new Panel();
1921 bot.setLayout(new FlowLayout(FlowLayout.CENTER));
1922 bot.add(rename_b = new CbButton(filemgr.get_image("save.gif"),
1923 filemgr.text("rename_ok"),
1924 CbButton.LEFT, this));
1925 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
1926 filemgr.text("cancel"),
1927 CbButton.LEFT, this));
1933 public void click(CbButton b)
1935 if (b == rename_b) {
1936 // Check for an existing file
1937 String newstr = newname.getText().trim();
1938 if (newstr.length() == 0) return;
1939 RemoteFile already = file.directory.find(newstr);
1940 if (already != null) {
1941 new ErrorWindow(filemgr.text("rename_eexists", newstr));
1945 // Rename the real file
1946 int sl = file.path.lastIndexOf('/');
1947 String newpath = file.path.substring(0, sl)+"/"+newstr;
1948 String rv[] = filemgr.get_text(
1949 "rename.cgi?old="+filemgr.urlize(file.path)+
1950 "&new="+filemgr.urlize(newpath));
1951 if (rv[0].length() > 0) {
1952 new ErrorWindow(filemgr.text("rename_efailed", rv[0]));
1956 // Update data structure
1958 file.path = newpath;
1959 file.directory.delete(file);
1960 file.directory.add(file);
1962 FileNode parnode = (FileNode)filemgr.nodemap.get(file.directory);
1963 FileNode filenode = (FileNode)filemgr.nodemap.get(file);
1964 if (parnode != null && filenode != null) {
1965 filenode.text = file.name;
1966 parnode.ch.removeElement(filenode);
1967 parnode.add(filenode);
1969 filemgr.dirs.redraw();
1972 filemgr.show_files(filemgr.showing_files);
1975 else if (b == cancel_b)
1980 class MultiLabel extends BorderPanel
1982 public MultiLabel(String s, int max)
1987 public MultiLabel(String s, int max, int b)
1990 Vector v = new Vector();
1991 StringTokenizer tok = new StringTokenizer(s.trim(), " \t");
1993 while(tok.hasMoreTokens()) {
1994 String w = tok.nextToken();
1995 line = (line == null ? w : line+" "+w);
1996 if (line.length() > max || !tok.hasMoreTokens()) {
2001 setLayout(new GridLayout(v.size(), 1, 0, 0));
2002 for(int i=0; i<v.size(); i++)
2003 add(new Label((String)v.elementAt(i), Label.CENTER));
2007 class OverwriteWindow extends FixedFrame implements CbButtonCallback
2009 FileManager filemgr;
2010 RemoteFile src, already;
2012 CbButton ok, cancel;
2016 OverwriteWindow(FileManager p, RemoteFile a, RemoteFile s, int i)
2018 filemgr = p; src = s; already = a; idx = i;
2019 mode = filemgr.cut_mode;
2020 setLayout(new BorderLayout());
2021 setTitle(filemgr.text("over_title"));
2023 new MultiLabel(filemgr.text("over_msg", already.path), 30, 0));
2024 add("West", new Label(filemgr.text("over_new")));
2025 add("East", newname = new TextField(a.name, 30));
2027 Panel bot = new Panel();
2028 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
2029 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
2030 filemgr.text("over_ok"),
2031 CbButton.LEFT, this));
2032 bot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
2033 filemgr.text("cancel"),
2034 CbButton.LEFT, this));
2040 public void click(CbButton b)
2044 else if (b == ok && newname.getText().length() > 0) {
2045 // paste the file, but with a new name
2046 RemoteFile ap = already.directory;
2047 RemoteFile newalready = ap.find(newname.getText());
2048 if (newalready == src) {
2049 new ErrorWindow(filemgr.text("paste_eself"));
2052 if (newalready != null && (newalready.type == 0 ||
2053 newalready.type == 5)) {
2055 filemgr.text("paste_eover", newalready.path));
2058 String dpath = (ap.path.equals("/") ? "/" :
2059 ap.path+"/")+newname.getText();
2060 RemoteFile nf = filemgr.paste_file(src, already.directory,
2061 dpath, newalready, mode);
2062 if (filemgr.cut_mode && nf != null) {
2063 // Paste from the destination path from now on
2064 filemgr.cut_buffer[idx] = nf;
2079 SambaShare(String l)
2081 StringSplitter tok = new StringSplitter(l, ':');
2082 path = tok.nextToken();
2083 available = tok.nextToken().equals("1");
2084 writable = tok.nextToken().equals("1");
2085 guest = Integer.parseInt(tok.nextToken());
2086 comment = tok.nextToken();
2089 SambaShare(String p, boolean a, boolean w, int g, String c)
2100 return "path="+FileManager.urlize(path)+
2101 "&available="+(available ? 1 : 0)+
2102 "&writable="+(writable ? 1 : 0)+
2104 "&comment="+FileManager.urlize(comment);
2108 class DFSAdminExport
2112 String ro, rw, root;
2114 DFSAdminExport(String l)
2116 StringSplitter tok = new StringSplitter(l, ':');
2117 path = tok.nextToken();
2118 ro = tok.nextToken();
2119 rw = tok.nextToken();
2120 root = tok.nextToken();
2121 desc = tok.nextToken();
2124 DFSAdminExport(String p, String d, String ro, String rw, String root)
2133 String[] split(String s)
2135 StringTokenizer stok = new StringTokenizer(s, " ");
2136 String rv[] = new String[stok.countTokens()];
2137 for(int i=0; i<rv.length; i++)
2138 rv[i] = stok.nextToken();
2144 return "path="+FileManager.urlize(path)+
2145 "&ro="+FileManager.urlize(ro)+
2146 "&rw="+FileManager.urlize(rw)+
2147 "&root="+FileManager.urlize(root)+
2148 "&desc="+FileManager.urlize(desc);
2159 LinuxExport(String l)
2161 StringSplitter tok = new StringSplitter(l, ':');
2162 path = tok.nextToken();
2163 int c = tok.countTokens() / 3;
2164 host = new String[c];
2165 ro = new boolean[c];
2166 squash = new int[c];
2167 for(int i=0; tok.hasMoreTokens(); i++) {
2168 host[i] = tok.nextToken();
2169 ro[i] = tok.nextToken().equals("1");
2170 squash[i] = Integer.parseInt(tok.nextToken());
2174 LinuxExport(String p, String h[], String r[], String s[])
2181 String rv = "path="+FileManager.urlize(path)+
2182 "&count="+host.length;
2183 for(int i=0; i<host.length; i++) {
2184 rv += "&host"+i+"="+FileManager.urlize(host[i]);
2185 rv += "&ro"+i+"="+(ro[i] ? 1 : 0);
2186 rv += "&squash"+i+"="+squash[i];
2192 class SharingWindow extends FixedFrame implements CbButtonCallback
2194 CbButton save_b, cancel_b;
2196 FileManager filemgr;
2198 DFSAdminExport dexport;
2199 LinuxExport lexport;
2200 Checkbox samba_on, samba_off;
2201 Checkbox writable_on, writable_off;
2202 Checkbox available_on, available_off;
2203 Checkbox guest_on, guest_off, guest_only;
2207 Checkbox nfs_on, nfs_off;
2208 TextField rwhosts, rohosts, roothosts;
2209 Checkbox rw[] = new Checkbox[3], ro[] = new Checkbox[3],
2210 root[] = new Checkbox[3];
2213 Choice lro[], squash[];
2215 SharingWindow(RemoteFile f, FileManager p)
2217 file = f; filemgr = p;
2218 setTitle(filemgr.text("share_title", file.path));
2219 sshare = (SambaShare)filemgr.stab.get(file.path);
2220 Object nshare = filemgr.ntab.get(file.path);
2221 if (filemgr.nfsmode == 1)
2222 lexport = (LinuxExport)nshare;
2223 else if (filemgr.nfsmode == 2)
2224 dexport = (DFSAdminExport)nshare;
2227 setLayout(new BorderLayout());
2228 Panel samba = new Panel(), sl = new Panel(), sr = new Panel();
2229 samba.setLayout(new BorderLayout());
2230 Panel st = new Panel();
2231 st.setLayout(new GridLayout(2, 1));
2232 CheckboxGroup sg = new CheckboxGroup();
2233 st.add(samba_off = new Checkbox(filemgr.text("share_soff"), sg,
2235 st.add(samba_on = new Checkbox(filemgr.text("share_son"), sg,
2237 samba.add("North", st);
2239 Panel stop = new LinedPanel(filemgr.text("share_sheader"));
2240 setup_leftright(stop, sl, sr);
2242 comment = new TextField(sshare == null ? "" : sshare.comment, 25);
2243 add_item(filemgr.text("share_comment"), comment, sl, sr);
2245 Panel ap = new Panel();
2246 ap.setLayout(new GridLayout(1, 0));
2247 CheckboxGroup ag = new CheckboxGroup();
2248 ap.add(available_on = new Checkbox(filemgr.text("yes"), ag,
2249 sshare == null || sshare.available));
2250 ap.add(available_off = new Checkbox(filemgr.text("no"), ag,
2251 sshare != null && !sshare.available));
2252 add_item(filemgr.text("share_available"), ap, sl, sr);
2254 Panel wp = new Panel();
2255 wp.setLayout(new GridLayout(1, 0));
2256 CheckboxGroup wg = new CheckboxGroup();
2257 wp.add(writable_on = new Checkbox(filemgr.text("yes"), wg,
2258 sshare == null || sshare.writable));
2259 wp.add(writable_off = new Checkbox(filemgr.text("no"), wg,
2260 sshare != null && !sshare.writable));
2261 add_item(filemgr.text("share_writable"), wp, sl, sr);
2263 Panel gp = new Panel();
2264 gp.setLayout(new GridLayout(1, 0));
2265 CheckboxGroup gg = new CheckboxGroup();
2266 gp.add(guest_only = new Checkbox(filemgr.text("share_only"), gg,
2267 sshare != null && sshare.guest == 2));
2268 gp.add(guest_on = new Checkbox(filemgr.text("yes"), gg,
2269 sshare == null || sshare.guest == 1));
2270 gp.add(guest_off = new Checkbox(filemgr.text("no"), gg,
2271 sshare != null && sshare.guest == 0));
2272 add_item(filemgr.text("share_guest"), gp, sl, sr);
2274 samba.add("Center", stop);
2277 Panel nfs = new Panel(), nl = new Panel(), nr = new Panel();
2278 nfs.setLayout(new BorderLayout());
2279 Panel nt = new Panel();
2280 nt.setLayout(new GridLayout(2, 1));
2281 CheckboxGroup ng = new CheckboxGroup();
2282 nt.add(nfs_off = new Checkbox(filemgr.text("share_noff"), ng,
2284 nt.add(nfs_on = new Checkbox(filemgr.text("share_non"), ng,
2286 nfs.add("North", nt);
2288 Panel ntop = new LinedPanel(filemgr.text("share_nheader"));
2289 setup_leftright(ntop, nl, nr);
2290 if (filemgr.nfsmode == 1) {
2291 // Linux export mode
2292 nl.setLayout(new GridLayout(0, 1, 2, 2));
2293 nr.setLayout(new GridLayout(0, 1, 2, 2));
2294 nl.add(new Label(filemgr.text("share_host")));
2295 nr.add(new Label(filemgr.text("share_opts")));
2296 int c = lexport==null ? 0 : lexport.host.length;
2297 host = new TextField[c+1];
2298 lro = new Choice[c+1];
2299 squash = new Choice[c+1];
2300 for(int i=0; i<c; i++) {
2301 host[i] = new TextField(lexport.host[i], 20);
2302 lro[i] = robox(lexport.ro[i]);
2303 squash[i] = squashbox(lexport.squash[i]);
2305 nr.add(opts_panel(lro[i], squash[i]));
2307 host[c] = new TextField("", 20);
2308 lro[c] = robox(false);
2309 squash[c] = squashbox(1);
2311 nr.add(opts_panel(lro[c], squash[c]));
2313 else if (filemgr.nfsmode == 2) {
2314 // Solaris share mode
2315 desc = new TextField(dexport == null ? "" : dexport.desc, 25);
2316 add_item(filemgr.text("share_desc"), desc, nl, nr);
2318 rohosts = add_hosts(filemgr.text("share_ro"),
2319 dexport == null ? "-" : dexport.ro,
2321 rwhosts = add_hosts(filemgr.text("share_rw"),
2322 dexport == null ? "-" : dexport.rw,
2324 roothosts = add_hosts(filemgr.text("share_root"),
2325 dexport == null ? "-" : dexport.root,
2327 root[1].getParent().remove(root[1]);
2329 else if (filemgr.nfsmode == 3) {
2331 nfs.add("Center", ntop);
2333 // Add the appropriate tabs
2334 if (filemgr.sambamode && filemgr.nfsmode != 0) {
2335 TabbedPanel tab = new TabbedPanel();
2336 tab.addItem(filemgr.text("share_samba"), samba);
2337 tab.addItem(filemgr.text("share_nfs"), nfs);
2340 else if (filemgr.sambamode)
2341 add("Center", samba);
2342 else if (filemgr.nfsmode != 0)
2345 // Create save and cancel buttons
2346 Panel bot = new Panel();
2347 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
2348 bot.add(save_b = new CbButton(filemgr.get_image("save.gif"),
2349 filemgr.text("save"),
2350 CbButton.LEFT, this));
2351 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2352 filemgr.text("cancel"),
2353 CbButton.LEFT, this));
2359 public void click(CbButton b)
2362 // Update samba settings on server
2363 if (sshare != null && samba_on.getState()) {
2365 sshare.available = available_on.getState();
2366 sshare.writable = writable_on.getState();
2367 sshare.guest = guest_only.getState() ? 2 :
2368 guest_on.getState() ? 1 : 0;
2369 sshare.comment = comment.getText();
2370 String rv[] = filemgr.get_text(
2371 "save_share.cgi?"+sshare.params());
2373 else if (sshare != null) {
2375 String rv[] = filemgr.get_text(
2376 "save_share.cgi?delete=1&"+sshare.params());
2377 filemgr.stab.remove(sshare.path);
2379 else if (samba_on.getState()) {
2381 sshare = new SambaShare(file.path,
2382 available_on.getState(),
2383 writable_on.getState(),
2384 guest_only.getState() ? 2 :
2385 guest_on.getState() ? 1 : 0,
2387 filemgr.stab.put(sshare.path, sshare);
2388 String rv[] = filemgr.get_text(
2389 "save_share.cgi?new=1&"+sshare.params());
2392 // Update NFS settings on server
2393 if (filemgr.nfsmode == 1) {
2394 if (lexport != null && nfs_on.getState()) {
2396 export_options(lexport);
2397 String rv[] = filemgr.get_text(
2398 "save_export.cgi?"+lexport.params());
2400 else if (lexport != null) {
2402 String rv[] = filemgr.get_text(
2403 "save_export.cgi?delete=1&"+lexport.params());
2404 filemgr.ntab.remove(lexport.path);
2406 else if (nfs_on.getState()) {
2408 lexport = new LinuxExport(file.path, null,
2410 export_options(lexport);
2411 String rv[] = filemgr.get_text(
2412 "save_export.cgi?new=1&"+lexport.params());
2413 filemgr.ntab.put(lexport.path, lexport);
2416 else if (filemgr.nfsmode == 2) {
2417 if (dexport != null && nfs_on.getState()) {
2419 dexport.desc = desc.getText();
2420 dexport.ro = ro[0].getState() ? "-" :
2421 ro[1].getState() ? "" :
2423 dexport.rw = rw[0].getState() ? "-" :
2424 rw[1].getState() ? "" :
2426 dexport.root = root[0].getState() ? "-" :
2427 roothosts.getText();
2428 String rv[] = filemgr.get_text(
2429 "save_export.cgi?"+dexport.params());
2431 else if (dexport != null) {
2433 String rv[] = filemgr.get_text(
2434 "save_export.cgi?delete=1&"+dexport.params());
2435 filemgr.ntab.remove(dexport.path);
2437 else if (nfs_on.getState()) {
2438 // Creating new share
2439 dexport = new DFSAdminExport(file.path,
2441 ro[0].getState() ? "-" :
2442 ro[1].getState() ? "" :
2444 rw[0].getState() ? "-" :
2445 rw[1].getState() ? "" :
2447 root[0].getState() ? "-" :
2448 roothosts.getText());
2449 String rv[] = filemgr.get_text(
2450 "save_export.cgi?new=1&"+dexport.params());
2451 filemgr.ntab.put(dexport.path, dexport);
2454 else if (filemgr.nfsmode == 3) {
2457 filemgr.show_files(filemgr.showing_files);
2460 else if (b == cancel_b)
2464 void setup_leftright(Panel m, Panel l, Panel r)
2466 m.setLayout(new BorderLayout());
2467 Panel p = new Panel();
2468 p.setLayout(new BorderLayout());
2471 l.setLayout(new GridLayout(0, 1));
2472 r.setLayout(new GridLayout(0, 1));
2476 void add_item(String t, Component c, Panel l, Panel r)
2478 l.add(new Label(t));
2479 Panel p = new Panel();
2480 p.setLayout(new BorderLayout());
2485 TextField add_hosts(String name, String v, Checkbox cb[],
2488 Panel p = new Panel();
2489 p.setLayout(new GridLayout(1, 3));
2490 CheckboxGroup g = new CheckboxGroup();
2491 p.add(cb[0] = new Checkbox(filemgr.text("share_none"), g,
2493 p.add(cb[1] = new Checkbox(filemgr.text("share_all"), g,
2495 p.add(cb[2] = new Checkbox(filemgr.text("share_listed"), g,
2497 add_item(name, p, l, r);
2498 TextField t = new TextField(v.equals("-") ? "" : v, 25);
2499 add_item("", t, l, r);
2503 Choice squashbox(int s)
2505 Choice rv = new Choice();
2506 rv.addItem(filemgr.text("share_s0"));
2507 rv.addItem(filemgr.text("share_s1"));
2508 rv.addItem(filemgr.text("share_s2"));
2513 Choice robox(boolean r)
2515 Choice rv = new Choice();
2516 rv.addItem(filemgr.text("share_lrw"));
2517 rv.addItem(filemgr.text("share_lro"));
2518 rv.select(r ? 1 : 0);
2522 Panel opts_panel(Component ro, Component squash)
2524 Panel p = new Panel();
2525 p.setLayout(new BorderLayout());
2527 p.add("East", squash);
2531 void export_options(LinuxExport e)
2534 for(int i=0; i<host.length; i++)
2535 if (host[i].getText().length() > 0)
2537 e.host = new String[c];
2538 e.ro = new boolean[c];
2539 e.squash = new int[c];
2540 for(int i=0,j=0; i<host.length; i++) {
2541 if (host[i].getText().trim().length() > 0) {
2542 e.host[j] = host[i].getText();
2543 e.ro[j] = lro[i].getSelectedIndex() == 1;
2544 e.squash[j] = squash[i].getSelectedIndex();
2552 class SearchWindow extends FixedFrame
2553 implements CbButtonCallback,MultiColumnCallback
2557 CbButton search_b, cancel_b;
2558 FileManager filemgr;
2559 TextField dir, match, user, group;
2560 Checkbox uany, usel, gany, gsel;
2562 Checkbox sany, smore, sless;
2563 TextField more, less;
2565 String types[] = { "", "f", "d", "l", "p" };
2566 RemoteFile results[];
2568 SearchWindow(String d, FileManager p)
2571 setTitle(filemgr.text("search_title"));
2574 setLayout(new BorderLayout());
2575 tab = new TabbedPanel();
2576 Panel search = new Panel();
2577 search.setLayout(new BorderLayout());
2578 tab.addItem(filemgr.text("search_crit"), search);
2579 Panel l = new Panel(), r = new Panel();
2580 l.setLayout(new GridLayout(0, 1));
2581 r.setLayout(new GridLayout(0, 1));
2583 String cols[] = { "", filemgr.text("right_name"),
2584 filemgr.text("right_size") };
2585 float widths[] = { .07f, .78f, .15f };
2586 list = new MultiColumn(cols, this);
2587 list.setWidths(widths);
2588 list.setDrawLines(false);
2589 tab.addItem(filemgr.text("search_list"), list);
2591 add_item(filemgr.text("search_dir"), dir = new TextField(d, 30), l, r);
2593 add_item(filemgr.text("search_match"), match = new TextField(20), l, r);
2595 Panel up = new Panel();
2596 up.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
2597 CheckboxGroup ug = new CheckboxGroup();
2598 up.add(uany = new Checkbox(filemgr.text("search_any"), ug, true));
2599 up.add(usel = new Checkbox("", ug, false));
2600 up.add(user = new TextField(10));
2601 add_item(filemgr.text("search_user"), up, l, r);
2603 Panel gp = new Panel();
2604 gp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
2605 CheckboxGroup gg = new CheckboxGroup();
2606 gp.add(gany = new Checkbox(filemgr.text("search_any"), gg, true));
2607 gp.add(gsel = new Checkbox("", gg, false));
2608 gp.add(group = new TextField(10));
2609 add_item(filemgr.text("search_group"), gp, l, r);
2611 type = new Choice();
2612 for(int i=0; i<types.length; i++)
2613 type.addItem(filemgr.text("search_types_"+types[i]));
2614 add_item(filemgr.text("search_type"), type, l, r);
2616 CheckboxGroup sg = new CheckboxGroup();
2617 add_item(filemgr.text("search_size"),
2618 sany = new Checkbox(filemgr.text("search_any"), sg, true),
2620 Panel mp = new Panel();
2621 mp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
2622 mp.add(smore = new Checkbox(filemgr.text("search_more"), sg, false));
2623 mp.add(more = new TextField(10));
2624 add_item("", mp, l, r);
2625 Panel lp = new Panel();
2626 lp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
2627 lp.add(sless = new Checkbox(filemgr.text("search_less"), sg, false));
2628 lp.add(less = new TextField(10));
2629 add_item("", lp, l, r);
2631 CheckboxGroup xg = new CheckboxGroup();
2632 Panel xp = new Panel();
2633 xp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
2634 xp.add(xoff = new Checkbox(filemgr.text("yes"), xg, true));
2635 xp.add(xon = new Checkbox(filemgr.text("no"), xg, false));
2636 add_item(filemgr.text("search_xdev"), xp, l, r);
2638 search.add("West", l); search.add("East", r);
2641 // Create search and cancel buttons
2642 Panel bot = new Panel();
2643 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
2644 bot.add(search_b = new CbButton(filemgr.get_image("save.gif"),
2645 filemgr.text("search_ok"),
2646 CbButton.LEFT, this));
2647 bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
2648 filemgr.text("cancel"),
2649 CbButton.LEFT, this));
2655 void add_item(String t, Component c, Panel l, Panel r)
2657 l.add(new Label(t));
2658 Panel p = new Panel();
2659 p.setLayout(new BorderLayout());
2664 public void click(CbButton b)
2668 else if (b == search_b) {
2669 // validate inputs and build search URL
2670 String url = "search.cgi";
2671 String d = dir.getText().trim();
2672 if (d.length() == 0 || d.charAt(0) != '/') {
2673 new ErrorWindow(filemgr.text("search_edir"));
2676 url += "?dir="+filemgr.urlize(d);
2677 String mt = match.getText().trim();
2678 if (mt.length() == 0) {
2679 new ErrorWindow(filemgr.text("search_ematch"));
2682 url += "&match="+filemgr.urlize(mt);
2683 if (type.getSelectedIndex() > 0)
2684 url += "&type="+types[type.getSelectedIndex()];
2685 if (usel.getState()) {
2686 String u = user.getText().trim();
2687 if (u.length() == 0) {
2688 new ErrorWindow(filemgr.text("search_euser"));
2691 url += "&user="+filemgr.urlize(u);
2693 if (gsel.getState()) {
2694 String g = group.getText().trim();
2695 if (g.length() == 0) {
2696 new ErrorWindow(filemgr.text("search_egroup"));
2699 url += "&group="+filemgr.urlize(g);
2701 if (smore.getState()) {
2702 String m = more.getText().trim();
2703 try { Integer.parseInt(m); }
2704 catch(Exception e) {
2705 new ErrorWindow(filemgr.text("search_esize"));
2708 url += "&size=%2B"+m+"c";
2710 else if (sless.getState()) {
2711 String l = less.getText().trim();
2712 try { Integer.parseInt(l); }
2713 catch(Exception e) {
2714 new ErrorWindow(filemgr.text("search_esize"));
2717 url += "&size=%2D"+l+"c";
2722 // send off the search
2723 setCursor(WAIT_CURSOR);
2724 String f[] = filemgr.get_text(url);
2725 if (f[0].length() > 0) {
2726 new ErrorWindow(f[0]);
2729 Object rows[][] = new Object[f.length-1][];
2730 results = new RemoteFile[f.length-1];
2731 for(int i=1; i<f.length; i++) {
2732 RemoteFile r = new RemoteFile(filemgr, f[i], null);
2734 Object row[] = rows[i-1] = new Object[3];
2735 row[0] = filemgr.get_image(RemoteFile.tmap[r.type]);
2738 row[2] = filemgr.spad(r.size, 5)+" B";
2739 else if (r.size < 1000000)
2740 row[2] = filemgr.spad(r.size/1000, 5)+" kB";
2742 row[2] = filemgr.spad(r.size/1000000, 5)+" MB";
2745 list.addItems(rows);
2746 tab.select(filemgr.text("search_list"));
2747 setCursor(DEFAULT_CURSOR);
2751 public void singleClick(MultiColumn list, int num)
2755 // go to the directory of the double-clicked file
2756 public void doubleClick(MultiColumn list, int num)
2758 RemoteFile f = results[num];
2759 int sl = f.path.lastIndexOf('/');
2760 String dir = sl == 0 ? "/" : f.path.substring(0, sl);
2761 filemgr.find_directory(dir, true);
2762 RemoteFile l[] = filemgr.showing_list;
2763 for(int i=0; i<l.length; i++) {
2764 if (l[i].name.equals(f.name)) {
2765 // select the file in the list
2766 filemgr.files.select(i+1);
2767 filemgr.files.scrollto(i+1);
2774 public void headingClicked(MultiColumn list, int col)
2789 FileSystem(String l)
2791 StringSplitter tok = new StringSplitter(l, ' ');
2792 mount = tok.nextToken();
2793 dev = tok.nextToken();
2794 type = tok.nextToken();
2795 String optstr = tok.nextToken();
2796 acls = tok.nextToken().equals("1");
2797 attrs = tok.nextToken().equals("1");
2798 ext = tok.nextToken().equals("1");
2800 StringTokenizer tok2 = new StringTokenizer(optstr, ",");
2801 opts = new String[tok2.countTokens()];
2802 for(int i=0; i<opts.length; i++)
2803 opts[i] = tok2.nextToken();
2809 FileManager filemgr;
2814 boolean read, write, exec;
2816 ACLEntry(String l, ACLWindow w)
2818 filemgr = w.filemgr;
2820 StringSplitter tok = new StringSplitter(l, ':');
2821 type = tok.nextToken();
2822 if (type.equals("default")) {
2824 type = tok.nextToken();
2826 if (!type.equals("mask") && !type.equals("other")) {
2827 owner = tok.nextToken();
2828 if (owner.length() == 0)
2831 String rwx = tok.nextToken();
2832 if (rwx.length() == 0)
2833 rwx = tok.nextToken(); // getfacl outputs a blank owner for mask
2834 // and other on some systems
2835 read = (rwx.charAt(0) == 'r');
2836 write = (rwx.charAt(1) == 'w');
2837 exec = (rwx.charAt(2) == 'x');
2840 ACLEntry(ACLWindow w)
2842 filemgr = w.filemgr;
2848 String rv[] = new String[3];
2849 String t = def ? "acltype_default_"+type : "acltype_"+type;
2850 rv[0] = filemgr.text(t);
2851 if (type.equals("mask") || type.equals("other") ||
2852 (def && owner == null))
2854 else if (owner != null)
2856 else if (type.equals("user"))
2857 rv[1] = filemgr.text("eacl_user", file.user);
2859 rv[1] = filemgr.text("eacl_group", file.group);
2861 if (read) rv[2] += filemgr.text("info_read")+" ";
2862 if (write) rv[2] += filemgr.text("info_write")+" ";
2863 if (exec) rv[2] += filemgr.text("info_exec")+" ";
2867 public String toString()
2869 String rv = def ? "default:" : "";
2871 if (!type.equals("mask") && !type.equals("other"))
2872 rv += (owner == null ? "" : owner)+":";
2873 rv += (read ? 'r' : '-');
2874 rv += (write ? 'w' : '-');
2875 rv += (exec ? 'x' : '-');
2880 class ACLEditor extends FixedFrame implements CbButtonCallback
2882 FileManager filemgr;
2887 Checkbox read, write, exec, owner1, owner2;
2890 // Editing an existing ACL entry
2891 ACLEditor(ACLWindow w, ACLEntry a)
2894 filemgr = aclwin.filemgr;
2900 // Creating a new ACL entry
2901 ACLEditor(ACLWindow w, String type, boolean def)
2904 filemgr = aclwin.filemgr;
2905 acl = new ACLEntry(aclwin);
2914 setTitle(filemgr.text(creating ? "eacl_create" : "eacl_edit"));
2915 setLayout(new BorderLayout());
2916 Panel left = new Panel();
2917 left.setLayout(new GridLayout(0, 1));
2919 Panel right = new Panel();
2920 right.setLayout(new GridLayout(0, 1));
2923 left.add(new Label(filemgr.text("eacl_acltype")));
2925 right.add(type = new TextField(
2926 (acl.def ? "default " : "")+acl.type, 20));
2927 type.setEditable(false);
2929 if (!acl.type.equals("mask") && !acl.type.equals("other")) {
2930 left.add(new Label(filemgr.text("eacl_aclname")));
2932 // A default user or group ACL .. can be for
2933 // a specific user, or for the file owner
2934 Panel op = new Panel();
2935 op.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
2936 CheckboxGroup gr = new CheckboxGroup();
2937 op.add(owner1 = new Checkbox(filemgr.text("eacl_owner"),
2938 gr, acl.owner == null));
2939 op.add(owner2 = new Checkbox("",
2940 gr, acl.owner != null));
2941 op.add(owner = new TextField(
2942 acl.owner == null ? "" : acl.owner, 20));
2945 else if (creating || acl.owner != null) {
2946 // A user or group ACL for a specific user
2947 owner = new TextField(
2948 acl.owner == null ? "" : acl.owner, 20);
2952 // A user or group ACL for the file owner
2954 if (acl.type.equals("user"))
2955 str = filemgr.text("eacl_user", aclwin.file.user);
2957 str = filemgr.text("eacl_group", aclwin.file.group);
2958 TextField o = new TextField(str);
2959 o.setEditable(false);
2964 left.add(new Label(filemgr.text("eacl_aclperms")));
2965 Panel pp = new Panel();
2966 pp.setLayout(new FlowLayout(FlowLayout.RIGHT));
2967 pp.add(read = new Checkbox(filemgr.text("info_read"), null, acl.read));
2968 pp.add(write = new Checkbox(filemgr.text("info_write"), null, acl.write));
2969 pp.add(exec = new Checkbox(filemgr.text("info_exec"), null, acl.exec));
2972 Panel bot = new Panel();
2973 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
2974 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
2975 filemgr.text("save"),
2976 CbButton.LEFT, this));
2977 if (!creating && (acl.owner != null || acl.def))
2978 bot.add(del = new CbButton(filemgr.get_image("cancel.gif"),
2979 filemgr.text("delete"),
2980 CbButton.LEFT, this));
2987 public void click(CbButton b)
2990 // Update or add the ACL entry
2991 if (owner1 != null && owner1.getState()) {
2994 else if (owner != null) {
2995 String o = owner.getText().trim();
2996 if (o.length() == 0 && !acl.def) {
2997 new ErrorWindow(filemgr.text("eacl_eowner"));
3000 acl.owner = owner.getText();
3001 if (acl.owner.length() == 0)
3004 acl.read = read.getState();
3005 acl.write = write.getState();
3006 acl.exec = exec.getState();
3008 // Add to the ACL table
3009 aclwin.acllist.addElement(acl);
3010 aclwin.acltable.addItem(acl.getRow());
3014 int idx = aclwin.acllist.indexOf(acl);
3015 aclwin.acltable.modifyItem(acl.getRow(), idx);
3019 else if (b == del) {
3020 // Remove this entry
3021 int idx = aclwin.acllist.indexOf(acl);
3022 aclwin.acllist.removeElementAt(idx);
3023 aclwin.acltable.deleteItem(idx);
3028 public void dispose()
3030 aclwin.edmap.remove(acl);
3035 class ACLWindow extends FixedFrame implements CbButtonCallback,MultiColumnCallback
3037 FileManager filemgr;
3039 Vector acllist = new Vector();
3040 Hashtable edmap = new Hashtable();
3042 CbButton ok, cancel, add;
3044 MultiColumn acltable;
3046 String acltypes[] = { "user", "group", "mask",
3047 "default user", "default group", "default other",
3050 ACLWindow(FileManager p, RemoteFile f)
3053 setTitle(p.text("eacl_title", f.path));
3058 String a[] = filemgr.get_text(
3059 "getfacl.cgi?file="+filemgr.urlize(file.path));
3060 if (a[0].length() != 0) {
3061 new ErrorWindow(filemgr.text("eacl_eacls", a[0]));
3066 setLayout(new BorderLayout());
3067 String titles[] = { filemgr.text("eacl_acltype"),
3068 filemgr.text("eacl_aclname"),
3069 filemgr.text("eacl_aclperms") };
3070 acltable = new MultiColumn(titles, this);
3071 for(int i=1; i<a.length; i++) {
3072 ACLEntry acl = new ACLEntry(a[i], this);
3073 acllist.addElement(acl);
3074 acltable.addItem(acl.getRow());
3076 add("Center", acltable);
3077 Panel abot = new Panel();
3078 abot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3079 abot.add(add = new CbButton(filemgr.get_image("add.gif"),
3080 filemgr.text("eacl_add"),
3081 CbButton.LEFT, this));
3082 int len = file.type == RemoteFile.DIR ? acltypes.length : 3;
3083 abot.add(addtype = new Choice());
3084 for(int i=0; i<len; i++) {
3085 String t = "acltype_"+acltypes[i].replace(' ', '_');
3086 addtype.addItem(filemgr.text(t));
3088 abot.add(new Label(" "));
3089 abot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3090 filemgr.text("save"),
3091 CbButton.LEFT, this));
3092 abot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
3093 filemgr.text("cancel"),
3094 CbButton.LEFT, this));
3101 public void click(CbButton b)
3104 // Check if there are any defaults, and if so there must
3105 // be default user, group and other
3106 boolean anydef = false, defuser = false,
3107 defgroup = false, defother = false;
3108 for(int i=0; i<acllist.size(); i++) {
3109 ACLEntry e = (ACLEntry)acllist.elementAt(i);
3110 if (e.def) anydef = true;
3111 if (e.def && e.owner == null) {
3112 if (e.type.equals("user")) defuser = true;
3113 if (e.type.equals("group")) defgroup = true;
3114 if (e.type.equals("other")) defother = true;
3117 if (anydef && (!defuser || !defgroup || !defother)) {
3118 new ErrorWindow(filemgr.text("eacl_edefaults"));
3124 for(int i=0; i<acllist.size(); i++)
3125 aclstr += (ACLEntry)acllist.elementAt(i)+"\n";
3126 String rv[] = filemgr.get_text("setfacl.cgi?file="+
3127 filemgr.urlize(file.path)+
3128 "&acl="+filemgr.urlize(aclstr));
3129 if (rv[0].length() > 0)
3130 new ErrorWindow(filemgr.text("eacl_efailed",
3135 else if (b == add) {
3136 // Open a window for a new ACL entry
3137 String t = acltypes[addtype.getSelectedIndex()];
3138 String d = "default ";
3139 boolean def = t.startsWith(d);
3141 t = t.substring(d.length());
3142 if (t.equals("mask")) {
3143 // Only allow one mask
3144 for(int i=0; i<acllist.size(); i++) {
3145 ACLEntry a = (ACLEntry)acllist.elementAt(i);
3146 if (a.type.equals(t) && a.def == def) {
3147 new ErrorWindow(filemgr.text(def ?
3148 "eacl_edefmask" : "eacl_emask"));
3153 new ACLEditor(this, t, def);
3155 else if (b == cancel) {
3161 // Bring up an editor for an ACL
3162 public void doubleClick(MultiColumn list, int num)
3164 int idx = list.selected();
3166 ACLEntry e = (ACLEntry)acllist.elementAt(idx);
3167 ACLEditor ed = (ACLEditor)edmap.get(e);
3169 edmap.put(e, new ACLEditor(this, e));
3177 public void singleClick(MultiColumn list, int num)
3181 public void headingClicked(MultiColumn list, int col)
3186 class AttributesWindow extends FixedFrame
3187 implements CbButtonCallback,MultiColumnCallback
3189 FileManager filemgr;
3191 Vector attrlist = new Vector();
3192 Hashtable edmap = new Hashtable();
3194 CbButton ok, cancel, add;
3195 MultiColumn attrtable;
3197 AttributesWindow(FileManager p, RemoteFile f)
3200 setTitle(p.text("attr_title", f.path));
3204 // Get the attributes
3205 String a[] = filemgr.get_text(
3206 "getattrs.cgi?file="+filemgr.urlize(file.path));
3207 if (a[0].length() != 0) {
3208 new ErrorWindow(filemgr.text("attr_eattrs", a[0]));
3213 setLayout(new BorderLayout());
3214 String titles[] = { filemgr.text("attr_name"),
3215 filemgr.text("attr_value") };
3216 attrtable = new MultiColumn(titles, this);
3217 for(int i=1; i<a.length; i++) {
3218 FileAttribute at = new FileAttribute(a[i], filemgr);
3219 attrlist.addElement(at);
3220 attrtable.addItem(at.getRow());
3222 add("Center", attrtable);
3223 Panel abot = new Panel();
3224 abot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3225 abot.add(add = new CbButton(filemgr.get_image("add.gif"),
3226 filemgr.text("attr_add"),
3227 CbButton.LEFT, this));
3228 abot.add(new Label(" "));
3229 abot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3230 filemgr.text("save"),
3231 CbButton.LEFT, this));
3232 abot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
3233 filemgr.text("cancel"),
3234 CbButton.LEFT, this));
3241 public void click(CbButton b)
3244 // Save the attributes
3246 for(int i=0; i<attrlist.size(); i++) {
3247 FileAttribute at = (FileAttribute)attrlist.elementAt(i);
3248 pstr += "&name"+i+"="+filemgr.urlize(at.name)+
3249 "&value"+i+"="+filemgr.urlize(at.value);
3251 String rv[] = filemgr.get_text("setattrs.cgi?file="+
3252 filemgr.urlize(file.path)+pstr);
3253 if (rv[0].length() > 0)
3254 new ErrorWindow(filemgr.text("attr_efailed",
3259 else if (b == add) {
3260 // Open a window for a new ACL entry
3261 new AttributeEditor(this);
3263 else if (b == cancel) {
3269 // Bring up an editor for an ACL
3270 public void doubleClick(MultiColumn list, int num)
3272 int idx = list.selected();
3274 FileAttribute at = (FileAttribute)attrlist.elementAt(idx);
3275 AttributeEditor ed = (AttributeEditor)edmap.get(at);
3277 edmap.put(at, new AttributeEditor(this, at));
3285 public void singleClick(MultiColumn list, int num)
3289 public void headingClicked(MultiColumn list, int col)
3299 FileAttribute(String l, FileManager f)
3301 int eq = l.indexOf('=');
3302 name = f.un_urlize(l.substring(0, eq));
3303 value = f.un_urlize(l.substring(eq+1));
3306 FileAttribute(String n, String v)
3314 return new String[] { name, value };
3318 class AttributeEditor extends FixedFrame implements CbButtonCallback
3320 FileManager filemgr;
3321 AttributesWindow attrwin;
3328 AttributeEditor(AttributesWindow w, FileAttribute a)
3332 filemgr = w.filemgr;
3337 AttributeEditor(AttributesWindow w)
3340 attr = new FileAttribute("", "");
3341 filemgr = w.filemgr;
3348 setTitle(filemgr.text(creating ? "attr_create" : "attr_edit"));
3349 setLayout(new BorderLayout());
3351 Panel top = new Panel();
3352 top.setLayout(new GridLayout(1, 2));
3353 top.add(new Label(filemgr.text("attr_name")));
3354 top.add(name = new TextField(attr.name, 20));
3357 Panel mid = new Panel();
3358 mid.setLayout(new GridLayout(1, 2));
3359 mid.add(new Label(filemgr.text("attr_value")));
3360 mid.add(value = new TextArea(attr.value, 5, 20));
3363 Panel bot = new Panel();
3364 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3365 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3366 filemgr.text("save"),
3367 CbButton.LEFT, this));
3369 bot.add(del = new CbButton(filemgr.get_image("cancel.gif"),
3370 filemgr.text("delete"),
3371 CbButton.LEFT, this));
3378 public void click(CbButton b)
3381 // Update or add the attribute
3382 if (name.getText().length() == 0) {
3383 new ErrorWindow(filemgr.text("attr_ename"));
3386 attr.name = name.getText();
3387 attr.value = value.getText();
3389 // Add to the attribs table
3390 attrwin.attrlist.addElement(attr);
3391 attrwin.attrtable.addItem(attr.getRow());
3395 int idx = attrwin.attrlist.indexOf(attr);
3396 attrwin.attrtable.modifyItem(attr.getRow(), idx);
3400 else if (b == del) {
3401 // Remove this entry
3402 int idx = attrwin.attrlist.indexOf(attr);
3403 attrwin.attrlist.removeElementAt(idx);
3404 attrwin.attrtable.deleteItem(idx);
3409 public void dispose()
3411 attrwin.edmap.remove(attr);
3416 class EXTWindow extends FixedFrame implements CbButtonCallback
3418 FileManager filemgr;
3421 CbButton ok, cancel;
3424 String attrs[] = { "A", "a", "c", "d", "i", "s", "S", "u" };
3425 Hashtable attrmap = new Hashtable();
3427 EXTWindow(FileManager p, RemoteFile f)
3430 setTitle(p.text("ext_title", f.path));
3434 // Get the attributes
3435 String a[] = filemgr.get_text(
3436 "getext.cgi?file="+filemgr.urlize(file.path));
3437 if (a[0].length() != 0) {
3438 new ErrorWindow(filemgr.text("ext_eattrs", a[0]));
3441 for(int i=0; i<a[1].length(); i++)
3442 attrmap.put(a[1].substring(i, i+1), "");
3445 setLayout(new BorderLayout());
3446 Panel top = new LinedPanel(filemgr.text("ext_header"));
3447 top.setLayout(new GridLayout(0, 1));
3448 cbs = new Checkbox[attrs.length];
3449 for(int i=0; i<attrs.length; i++) {
3450 cbs[i] = new Checkbox(filemgr.text("eattr_"+attrs[i]));
3451 cbs[i].setState(attrmap.get(attrs[i]) != null);
3456 Panel bot = new Panel();
3457 bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
3458 bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
3459 filemgr.text("save"),
3460 CbButton.LEFT, this));
3461 bot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
3462 filemgr.text("cancel"),
3463 CbButton.LEFT, this));
3470 public void click(CbButton b)
3473 // Save the attributes (including unknown ones)
3475 for(int i=0; i<cbs.length; i++) {
3476 if (cbs[i].getState())
3478 attrmap.remove(attrs[i]);
3480 for(Enumeration e = attrmap.keys(); e.hasMoreElements(); )
3481 astr += e.nextElement();
3483 // Try to set on the server
3484 String rv[] = filemgr.get_text("setext.cgi?file="+
3485 filemgr.urlize(file.path)+"&attrs="+astr);
3486 if (rv[0].length() > 0)
3487 new ErrorWindow(filemgr.text("ext_efailed",
3492 else if (b == cancel) {