import java.awt.*; import java.io.*; import java.applet.*; import java.net.*; import java.util.*; import netscape.javascript.JSObject; // A java filemanager that allows the user to manipulate files on the // Webmin server. Layout is similar to the windows explorer - directory // tree on the left, files on the right, action buttons on the top. public class FileManager extends Applet implements CbButtonCallback, HierarchyCallback, MultiColumnCallback { // top buttons CbButton ret_b, down_b, edit_b, refresh_b, props_b, copy_b, cut_b, paste_b, delete_b, new_b, upload_b, mkdir_b, makelink_b, rename_b, share_b, search_b, acl_b, attr_b, ext_b; // Directory tree Hierarchy dirs; FileNode root; Hashtable nodemap = new Hashtable(); // File list MultiColumn files; TextField pathname; RemoteFile showing_files; RemoteFile showing_list[]; // Copying and pasting RemoteFile cut_buffer[]; boolean cut_mode; static final String monmap[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; String accroot[]; Hashtable lang = new Hashtable(); Hashtable stab = new Hashtable(), ntab = new Hashtable(); boolean sambamode; int nfsmode; String trust; boolean got_filesystems; Vector fslist = new Vector(); boolean read_only = false; public void init() { setLayout(new BorderLayout()); StringTokenizer tok = new StringTokenizer(getParameter("root"), " "); accroot = new String[tok.countTokens()]; for(int i=0; tok.hasMoreTokens(); i++) accroot[i] = tok.nextToken(); trust = getParameter("trust"); // download language strings String l[] = get_text("lang.cgi"); for(int i=0; i= 0) lang.put(l[i].substring(0, eq), l[i].substring(eq+1)); } // list samba file shares String s[] = get_text("list_shares.cgi"); if (s[0].equals("1")) { for(int i=1; i 1) return new CbButton(get_image(f), this); else return new CbButton(get_image(f), t, CbButton.ABOVE, this); } // Gets an image from the images directory Image get_image(String img) { return getImage(getDocumentBase(), "images/"+img); } String[] get_text(String url) { try { long now = System.currentTimeMillis(); if (url.indexOf('?') > 0) url += "&rand="+now; else url += "?rand="+now; url += "&trust="+trust; URL u = new URL(getDocumentBase(), url); Vector lv = new Vector(); LineInputStream is = new LineInputStream(u.openStream()); while(true) try { lv.addElement(is.gets()); } catch(EOFException eof) { break; } is.close(); String rv[] = new String[lv.size()]; lv.copyInto(rv); return rv; } catch(Exception e) { e.printStackTrace(); //return null; String err[] = { e.getMessage() }; return err; } } // Fill the multicolumn list with files from some directory boolean show_files(RemoteFile f) { RemoteFile fl[] = f.list(); if (fl == null) return false; files.clear(); Object rows[][] = new Object[fl.length+1][]; long now = System.currentTimeMillis(); // Sort listing by chosen column if (f != showing_files) { // Directory has changed .. assume sort by name files.sortingArrow(1, 1); } else if (files.sortdir != 0) { // Sort by chosen order RemoteFile fls[] = new RemoteFile[fl.length]; System.arraycopy(fl, 0, fls, 0, fl.length); QuickSort.sort(fls, files.sortcol, files.sortdir); fl = fls; } // Create parent directory row rows[0] = new Object[6]; rows[0][0] = get_image("dir.gif"); rows[0][1] = ".."; rows[0][2] = rows[0][3] = rows[0][4] = rows[0][5] = ""; // Create file rows Date n = new Date(now); for(int i=0; i 0 || s == 0 && ss.length > 1) { // At least one non-.. file was selected boolean parentsel = false; for(int i=0; i 4) new ErrorWindow(text("edit_enormal")); else new EditorWindow(f, this); } else if (b == down_b) { // Force download of the selected file if (f == null) return; if (f.type == 0 || f.type > 4) new ErrorWindow(text("view_enormal2")); else show_file(f, true); } else if (b == refresh_b) { // Refesh the selected directory (and thus any subdirs) d.known = false; d.file.list = null; d.fill(); show_files(d.file); } else if (b == props_b) { // Display the properties window if (f == null) return; new PropertiesWindow(f, this); } else if (b == acl_b) { // Display the ACL window (if filesystem supports them) if (f == null) return; FileSystem filefs = find_filesys(f); if (filefs == null) return; if (filefs.acls) new ACLWindow(this, f); else new ErrorWindow(text("eacl_efs", filefs.mount)); } else if (b == attr_b) { // Display the attributes window (if filesystem supports them) if (f == null) return; FileSystem filefs = find_filesys(f); if (filefs == null) return; if (filefs.attrs) new AttributesWindow(this, f); else new ErrorWindow(text("attr_efs", filefs.mount)); } else if (b == ext_b) { // Display EXT attributes window (if filesystem supports them) if (f == null) return; FileSystem filefs = find_filesys(f); if (filefs == null) return; if (filefs.ext) new EXTWindow(this, f); else new ErrorWindow(text("ext_efs", filefs.mount)); } else if (b == copy_b) { // Copy the selected files if (f == null) return; cut_buffer = ff; cut_mode = false; } else if (b == cut_b) { // Cut the selected file if (f == null) return; cut_buffer = ff; cut_mode = true; } else if (b == paste_b) { // Paste the copied file if (cut_buffer == null) { new ErrorWindow(text("paste_ecopy")); return; } // Check for existing file clashes // XXX // Go through all the files to paste for(int i=0; i= rl && p.substring(0, rl).equals(accroot[r])) can = true; else if (l < rl && accroot[r].substring(0, l).equals(p)) can = true; } if (!can) { new ErrorWindow(text("find_eaccess", p)); return null; } FileNode posnode = root; RemoteFile pos = posnode.file; StringTokenizer tok = new StringTokenizer(p, "/"); while(tok.hasMoreTokens()) { String fn = tok.nextToken(); if (fn.equals("")) continue; RemoteFile fl[] = pos.list(); if (fl == null) return null; if (fill) { posnode.open = true; posnode.fill(); } boolean found = false; for(int i=0; i= l+1 && f.path.substring(0, l+1).equals(fs.mount+"/")) || fs.mount.equals("/")) { filefs = fs; } } return filefs; } public boolean action(Event e, Object o) { if (e.target == pathname) { // A new path was entered.. cd to it String p = pathname.getText().trim(); if (p.equals("")) return true; find_directory(p, true); return true; } return false; } // singleClick // Called on a single click on a list item public void singleClick(MultiColumn list, int num) { } // doubleClick // Called upon double-clicking on a list item public void doubleClick(MultiColumn list, int num) { if (num == 0) { // Go to parent directory if (showing_files.directory != null) { ((FileNode)nodemap.get(showing_files)).open = false; show_files(showing_files.directory); dirs.select((FileNode)nodemap.get(showing_files)); dirs.redraw(); } return; } RemoteFile d = showing_list[num-1]; if (d.type == 0) { // Open this directory FileNode pn = (FileNode)nodemap.get(showing_files); pn.fill(); pn.open = true; FileNode fn = (FileNode)nodemap.get(d); if (show_files(d)) { fn.fill(); fn.open = true; dirs.select(fn); dirs.redraw(); } } else if (d.type <= 4) { // Direct the browser to this file show_file(d, list.last_event.shiftDown()); } } // Called when the user clicks on a column heading so that it can // be sorted. public void headingClicked(MultiColumn list, int col) { if (col == 0) return; // ignore click on icon column? if (col == list.sortcol) { list.sortingArrow(col, list.sortdir == 2 ? 1 : 2); } else { list.sortingArrow(col, 1); } // Re-show the list in the new order, but with the same files selected int ss[] = files.allSelected(); RemoteFile ssf[] = new RemoteFile[ss.length]; for(int i=0; i 0) { ch.insertElementAt(n, i); break; } } } } class RemoteFile { static final int DIR = 0; static final int TEXT = 1; static final int IMAGE = 2; static final int BINARY = 3; static final int UNKNOWN = 4; static final int SYMLINK = 5; static final int DEVICE = 6; static final int PIPE = 7; static final String[] tmap = { "dir.gif", "text.gif", "image.gif", "binary.gif", "unknown.gif", "symlink.gif", "device.gif", "pipe.gif" }; FileManager parent; String path, name; int type; String user, group; long size; int perms; long modified; String linkto; RemoteFile list[]; RemoteFile directory; // Parse a line of text to a file object RemoteFile(FileManager parent, String line, RemoteFile d) { this.parent = parent; StringTokenizer tok = new StringTokenizer(line, "\t"); path = tok.nextToken(); type = Integer.parseInt(tok.nextToken()); user = tok.nextToken(); group = tok.nextToken(); size = Long.parseLong(tok.nextToken()); perms = Integer.parseInt(tok.nextToken()); modified = Long.parseLong(tok.nextToken())*1000; if (type == 5) linkto = tok.nextToken(); directory = d; if (path.equals("/")) name = "/"; else name = path.substring(path.lastIndexOf('/')+1); } // Create a new, empty file object RemoteFile() { } // Returns a list of files in this directory RemoteFile[] list() { if (list == null) { String l[] = parent.get_text("list.cgi?dir="+ parent.urlize(path)); if (l[0].length() > 0) { //list = new RemoteFile[0]; // Error reading the remote directory! new ErrorWindow(parent.text("list_edir", path, l[0])); list = null; } else { list = new RemoteFile[l.length-3]; for(int i=3; i 0 && offset == 0) { nlist[i] = f; offset++; } nlist[i+offset] = list[i]; } if (offset == 0) nlist[list.length] = f; list = nlist; } void delete(RemoteFile f) { RemoteFile nlist[] = new RemoteFile[list.length-1]; for(int i=0,j=0; i= 0) { // Length is known buf = new byte[uc.getContentLength()]; int got = 0; while(got < buf.length) got += is.read(buf, got, buf.length-got); } else { // Length is unknown .. read till the end buf = new byte[0]; while(true) { byte data[] = new byte[16384]; int got; try { got = is.read(data); } catch(EOFException ex) { break; } if (got <= 0) break; byte nbuf[] = new byte[buf.length + got]; System.arraycopy(buf, 0, nbuf, 0, buf.length); System.arraycopy(data, 0, nbuf, buf.length, got); buf = nbuf; } } edit.setText(new String(buf, 0)); is.close(); file.size = buf.length; } catch(Exception e) { e.printStackTrace(); } } // Creating a new file EditorWindow(String f, FileManager p) { super(500, 300); filemgr = p; makeUI(true); setTitle(filemgr.text("edit_title2")); name.setText(f.equals("/") ? f : f+"/"); name.select(name.getText().length(), name.getText().length()); } void makeUI(boolean add_name) { setLayout(new BorderLayout()); if (add_name) { Panel np = new Panel(); np.setLayout(new BorderLayout()); np.add("West", new Label(filemgr.text("edit_filename"))); np.add("Center", name = new TextField()); add("North", np); } add("Center", edit = new TextArea(20, 80)); edit.setFont(new Font("courier", Font.PLAIN, 14)); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.RIGHT)); bot.add(goto_b = new CbButton(filemgr.get_image("goto.gif"), filemgr.text("edit_goto"), CbButton.LEFT, this)); bot.add(find_b = new CbButton(filemgr.get_image("find.gif"), filemgr.text("edit_find"), CbButton.LEFT, this)); bot.add(new Label(" ")); bot.add(save_b = new CbButton(filemgr.get_image("save.gif"), filemgr.text("save"), CbButton.LEFT, this)); bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("cancel"), CbButton.LEFT, this)); add("South", bot); pack(); show(); } public void click(CbButton b) { if (b == save_b) { RemoteFile par = null, already = null; String save_path; if (file == null) { // Locate the filemgr directory save_path = filemgr.trim_path(name.getText()); int sl = save_path.lastIndexOf('/'); par = filemgr.find_directory( save_path.substring(0, sl), false); if (par == null) return; already = par.find(save_path.substring(sl+1)); if (already != null && (already.type == 0 || already.type == 5)) { new ErrorWindow( filemgr.text("edit_eover", save_path)); return; } } else save_path = file.path; // Save the file back again String s = edit.getText(), line; try { URL u = new URL(filemgr.getDocumentBase(), "save.cgi"+filemgr.urlize(save_path)+ "?rand="+System.currentTimeMillis()+ "&trust="+filemgr.trust); URLConnection uc = u.openConnection(); uc.setDoOutput(true); OutputStream os = uc.getOutputStream(); byte buf[] = new byte[s.length()]; s.getBytes(0, buf.length, buf, 0); os.write(buf); os.close(); LineInputStream is = new LineInputStream( uc.getInputStream()); String err = is.gets(); if (err.length() > 0) { new ErrorWindow( filemgr.text("edit_esave", err)); is.close(); return; } line = is.gets(); is.close(); } catch(Exception e) { e.printStackTrace(); return; } if (file == null) { // Create and insert or replace the file object file = new RemoteFile(filemgr, line, par); if (already != null) { // A file with this name exists already.type = file.type; already.user = file.user; already.group = file.group; already.size = file.size; already.perms = file.perms; already.modified = file.modified; } else { // Add to the list par.add(file); } } else { file.size = s.length(); file.modified = System.currentTimeMillis(); } filemgr.show_files(filemgr.showing_files); dispose(); } else if (b == cancel_b) { // Just close dispose(); } else if (b == goto_b) { // Open a dialog asking which line to go to if (goto_window != null) goto_window.toFront(); else goto_window = new GotoWindow(this); } else if (b == find_b) { // Open the search (and replace) dialog if (find_window != null) find_window.toFront(); else find_window = new FindReplaceWindow(this); } } public void dispose() { super.dispose(); if (goto_window != null) goto_window.dispose(); if (find_window != null) find_window.dispose(); } } class GotoWindow extends FixedFrame implements CbButtonCallback { EditorWindow editor; FileManager filemgr; TextField line; CbButton goto_b, cancel_b; GotoWindow(EditorWindow e) { editor = e; filemgr = e.filemgr; setLayout(new BorderLayout()); add("West", new Label(filemgr.text("edit_gotoline"))); add("Center", line = new TextField(10)); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.RIGHT)); bot.add(goto_b = new CbButton(filemgr.get_image("goto.gif"), filemgr.text("edit_goto"), CbButton.LEFT, this)); bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("close"), CbButton.LEFT, this)); add("South", bot); pack(); show(); } public void click(CbButton b) { if (b == goto_b) { // Go to the chose line, if it exists int lnum; try { lnum = Integer.parseInt(line.getText()); } catch(Exception e) { return; } String txt = editor.edit.getText(); int c, l = 0; for(c=0; c= 0) { String sel = edittxt.substring(st, en); if (sel.equals(findtxt)) { // Replace the selected editor.edit.setText(edittxt.substring(0, st)+ replace.getText()+ edittxt.substring(en)); editor.edit.select(st, st); return; } } click(find_b); } else if (b == all_b) { // Replace all occurrances of the text in the editor int pos = 0; int len = findtxt.length(); int st = editor.edit.getSelectionStart(), en = editor.edit.getSelectionEnd(); while((pos = edittxt.indexOf(findtxt, pos)) != -1) { edittxt = edittxt.substring(0, pos)+ replace.getText()+ edittxt.substring(pos+len); pos += len; } editor.edit.setText(edittxt); editor.edit.select(st, en); // put back old selection } else if (b == cancel_b) { // Just close the window dispose(); } } public void dispose() { super.dispose(); editor.find_window = null; } } class PropertiesWindow extends FixedFrame implements CbButtonCallback { RemoteFile file; FileManager filemgr; CbButton save_b, cancel_b; TextField linkto; TextField user, group; Checkbox setuid, setgid; PermissionsPanel user_p, group_p, other_p; Checkbox sticky; Choice rec_mode; TextField octal; PropertiesWindow(RemoteFile f, FileManager p) { file = f; filemgr = p; // Create UI setTitle(f.path); setLayout(new BorderLayout()); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.RIGHT)); bot.add(save_b = new CbButton(filemgr.get_image("save.gif"), filemgr.text("save"), CbButton.LEFT, this)); bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("cancel"), CbButton.LEFT, this)); add("South", bot); Panel mid = new Panel(); mid.setLayout(new BorderLayout()); TabbedPanel tab = null; add("Center", mid); // Create file details section Panel det = new LinedPanel(filemgr.text("info_file")), dl = new Panel(), dr = new Panel(); setup_leftright(det, dl, dr); add_item(filemgr.text("info_path"), new Label(file.path), dl, dr); add_item(filemgr.text("info_type"), new Label(filemgr.text("file_type"+file.type)), dl, dr); add_item(filemgr.text("info_size"), new Label(String.valueOf(file.size)),dl,dr); add_item(filemgr.text("info_mod"), new Label(String.valueOf(new Date(file.modified))), dl, dr); if (file.type == 5) add_item(filemgr.text("info_link"), linkto = new TextField(file.linkto, 30), dl, dr); mid = add_panel(mid, det); // Create permissions section Panel per = new LinedPanel(filemgr.text("info_perms")), pl = new Panel(), pr = new Panel(); setup_leftright(per, pl, pr); add_item(filemgr.text("info_user"), user_p = new PermissionsPanel(file, 64, filemgr), pl, pr); add_item(filemgr.text("info_group"), group_p = new PermissionsPanel(file, 8, filemgr), pl, pr); add_item(filemgr.text("info_other"), other_p = new PermissionsPanel(file, 1, filemgr), pl,pr); if (file.type == 0) { add_item(filemgr.text("info_sticky"), sticky = new Checkbox( filemgr.text("info_sticky2")), pl,pr); sticky.setState((file.perms&01000) != 0); } add_item(filemgr.text("info_octal"), octal = new TextField(4), pl, pr); octal.setEditable(false); mid = add_panel(mid, per); // Create ownership section Panel own = new LinedPanel(filemgr.text("info_own")), ol = new Panel(), or = new Panel(); setup_leftright(own, ol, or); add_item(filemgr.text("info_user"), user = new TextField(file.user, 10), ol, or); if (file.type != 0) { add_item(filemgr.text("info_setuid"), setuid = new Checkbox(filemgr.text("info_setuid2")), ol, or); setuid.setState((file.perms & 0x800) != 0); } add_item(filemgr.text("info_group"), group = new TextField(file.group, 10), ol, or); if (file.type == 0) add_item(filemgr.text("info_setgid"), setgid = new Checkbox(filemgr.text("info_setgid2")), ol, or); else add_item(filemgr.text("info_setgid"), setgid = new Checkbox(filemgr.text("info_setgid3")), ol, or); setgid.setState((file.perms & 0x400) != 0); mid = add_panel(mid, own); if (file.type == 0) { // Create recursion section Panel rec = new LinedPanel(filemgr.text("info_apply")); rec.setLayout(new BorderLayout()); rec_mode = new Choice(); for(int i=1; i<=3; i++) rec_mode.addItem(filemgr.text("info_apply"+i)); rec.add("Center", rec_mode); mid = add_panel(mid, rec); } set_octal(); pack(); show(); } Panel add_panel(Panel p, Component c) { p.add("North", c); Panel np = new Panel(); np.setLayout(new BorderLayout()); p.add("Center", np); return np; } public void click(CbButton b) { if (b == save_b) { // Update the file int perms = get_perms(); int rec = 0; if (file.type == 0) rec = rec_mode.getSelectedIndex(); String rv[] = filemgr.get_text( "chmod.cgi?path="+filemgr.urlize(file.path)+ "&perms="+perms+"&user="+user.getText()+ "&group="+group.getText()+"&rec="+rec+ (linkto==null ? "" : "&linkto="+linkto.getText())); if (rv[0].length() > 0) { // Something went wrong new ErrorWindow(filemgr.text("info_efailed", file.path, rv[0])); } else { // Update all changed file objects if (linkto != null) file.linkto = linkto.getText(); else if (rec == 0) update_file(file, perms, false); else if (rec == 1) { // Update files in this directory update_file(file, perms, false); recurse_files(file, perms, false); } else if (rec == 2) { // Update files and subdirs update_file(file, perms, false); recurse_files(file, perms, true); } // Update directory list int os = filemgr.files.selected(); filemgr.show_files(filemgr.showing_files); filemgr.files.select(os); dispose(); } } else { // Just close dispose(); } } void update_file(RemoteFile f, int perms, boolean perms_only) { f.user = user.getText(); f.group = group.getText(); if (perms_only) f.perms = (perms & 0777) | (f.perms & 037777777000); else f.perms = perms; } void recurse_files(RemoteFile f, int perms, boolean do_subs) { if (f.list == null) return; for(int i=0; i 1 ? "delete_mtitle" : ff[0].type == 0 ? "delete_dtitle" : "delete_ftitle")); setLayout(new BorderLayout()); if (ff.length > 1) { add("North", new Label(filemgr.text("delete_mdesc"))); Panel mp = new Panel(); mp.setLayout(new GridLayout(ff.length, 1)); for(int i=0; i 0) { new ErrorWindow(filemgr.text("delete_efailed", file.path, rv[0])); break; } else { // done the deed.. update data structures RemoteFile pf = file.directory; pf.delete(file); if (filemgr.showing_files == pf) { // Need to refresh the list as well.. need_reshow = true; } FileNode node = (FileNode)filemgr.nodemap.get( file); FileNode pnode = (FileNode)filemgr.nodemap.get( pf); if (node != null) { // Take the directory out of the tree.. pnode.ch.removeElement(node); need_redraw = true; } } } if (need_reshow) filemgr.show_files(filemgr.showing_files); if (need_redraw) filemgr.dirs.redraw(); dispose(); } else if (b == cancel_b) dispose(); } } class MkdirWindow extends FixedFrame implements CbButtonCallback { FileManager filemgr; TextField dir; CbButton create_b, cancel_b; MkdirWindow(String d, FileManager p) { filemgr = p; setTitle(filemgr.text("mkdir_title")); setLayout(new BorderLayout()); add("West", new Label(filemgr.text("mkdir_dir"))); add("Center", dir = new TextField(d.equals("/") ? "/" : d+"/", 40)); dir.select(dir.getText().length(), dir.getText().length()); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.CENTER)); bot.add(create_b = new CbButton(filemgr.get_image("save.gif"), filemgr.text("create"), CbButton.LEFT, this)); bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("cancel"), CbButton.LEFT, this)); add("South", bot); pack(); show(); } public void click(CbButton b) { if (b == create_b) { // Find the filemgr directory String path = dir.getText(); path = filemgr.trim_path(path); int sl = path.lastIndexOf('/'); RemoteFile par = filemgr.find_directory( path.substring(0, sl), false); if (par.find(path.substring(sl+1)) != null) { new ErrorWindow(filemgr.text("mkdir_eexists", path)); return; } String rv[] = filemgr.get_text("mkdir.cgi?dir="+ filemgr.urlize(path)); if (rv[0].length() > 0) { new ErrorWindow(filemgr.text("mkdir_efailed", rv[0])); return; } RemoteFile file = new RemoteFile(filemgr, rv[1], par); par.add(file); FileNode parnode = (FileNode)filemgr.nodemap.get(par); if (parnode != null) { // Update the tree parnode.add(new FileNode(file)); filemgr.dirs.redraw(); } filemgr.show_files(filemgr.showing_files); dispose(); } else dispose(); } } class LinkWindow extends FixedFrame implements CbButtonCallback { FileManager filemgr; TextField from, to; CbButton create_b, cancel_b; LinkWindow(String d, FileManager p) { filemgr = p; setLayout(new BorderLayout()); setTitle(filemgr.text("link_title")); Panel l = new Panel(), r = new Panel(); l.setLayout(new GridLayout(0, 1)); l.add(new Label(filemgr.text("link_from"))); l.add(new Label(filemgr.text("link_to"))); r.setLayout(new GridLayout(0, 1)); r.add(from = new TextField(d.equals("/") ? "/" : d+"/", 40)); from.select(from.getText().length(), from.getText().length()); r.add(to = new TextField()); add("West", l); add("Center", r); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.CENTER)); bot.add(create_b = new CbButton(filemgr.get_image("save.gif"), filemgr.text("create"), CbButton.LEFT, this)); bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("cancel"), CbButton.LEFT, this)); add("South", bot); pack(); show(); } public void click(CbButton b) { if (b == create_b) { // Check inputs String from_str = from.getText().trim(); int sl = from_str.lastIndexOf('/'); String par_str = from_str.substring(0, sl), file_str = from_str.substring(sl+1); RemoteFile par = filemgr.find_directory(par_str, false); if (par == null) return; if (par.find(file_str) != null) { new ErrorWindow(filemgr.text("link_eexists", from_str)); return; } // Create the actual link String rv[] = filemgr.get_text("makelink.cgi?from="+ filemgr.urlize(from_str)+"&to="+ filemgr.urlize(to.getText())); if (rv[0].length() > 0) { new ErrorWindow(filemgr.text("link_efailed", rv[0])); return; } RemoteFile file = new RemoteFile(filemgr, rv[1], par); par.add(file); filemgr.show_files(filemgr.showing_files); dispose(); } else if (b == cancel_b) dispose(); } } class RenameWindow extends FixedFrame implements CbButtonCallback { FileManager filemgr; RemoteFile file; TextField oldname, newname; CbButton rename_b, cancel_b; RenameWindow(FileManager p, RemoteFile f) { filemgr = p; file = f; setLayout(new BorderLayout()); setTitle(filemgr.text("rename_title", file.path)); Panel l = new Panel(), r = new Panel(); l.setLayout(new GridLayout(0, 1)); l.add(new Label(filemgr.text("rename_old"))); l.add(new Label(filemgr.text("rename_new"))); r.setLayout(new GridLayout(0, 1)); r.add(oldname = new TextField(file.name, 20)); oldname.setEditable(false); r.add(newname = new TextField(file.name, 20)); newname.select(file.name.length(), file.name.length()); add("West", l); add("Center", r); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.CENTER)); bot.add(rename_b = new CbButton(filemgr.get_image("save.gif"), filemgr.text("rename_ok"), CbButton.LEFT, this)); bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("cancel"), CbButton.LEFT, this)); add("South", bot); pack(); show(); } public void click(CbButton b) { if (b == rename_b) { // Check for an existing file String newstr = newname.getText().trim(); if (newstr.length() == 0) return; RemoteFile already = file.directory.find(newstr); if (already != null) { new ErrorWindow(filemgr.text("rename_eexists", newstr)); return; } // Rename the real file int sl = file.path.lastIndexOf('/'); String newpath = file.path.substring(0, sl)+"/"+newstr; String rv[] = filemgr.get_text( "rename.cgi?old="+filemgr.urlize(file.path)+ "&new="+filemgr.urlize(newpath)); if (rv[0].length() > 0) { new ErrorWindow(filemgr.text("rename_efailed", rv[0])); return; } // Update data structure file.name = newstr; file.path = newpath; file.directory.delete(file); file.directory.add(file); file.list = null; FileNode parnode = (FileNode)filemgr.nodemap.get(file.directory); FileNode filenode = (FileNode)filemgr.nodemap.get(file); if (parnode != null && filenode != null) { filenode.text = file.name; parnode.ch.removeElement(filenode); parnode.add(filenode); dispose(); filemgr.dirs.redraw(); } filemgr.show_files(filemgr.showing_files); dispose(); } else if (b == cancel_b) dispose(); } } class MultiLabel extends BorderPanel { public MultiLabel(String s, int max) { this(s, max, 1); } public MultiLabel(String s, int max, int b) { super(b); Vector v = new Vector(); StringTokenizer tok = new StringTokenizer(s.trim(), " \t"); String line = null; while(tok.hasMoreTokens()) { String w = tok.nextToken(); line = (line == null ? w : line+" "+w); if (line.length() > max || !tok.hasMoreTokens()) { v.addElement(line); line = null; } } setLayout(new GridLayout(v.size(), 1, 0, 0)); for(int i=0; i 0) { // paste the file, but with a new name RemoteFile ap = already.directory; RemoteFile newalready = ap.find(newname.getText()); if (newalready == src) { new ErrorWindow(filemgr.text("paste_eself")); return; } if (newalready != null && (newalready.type == 0 || newalready.type == 5)) { new ErrorWindow( filemgr.text("paste_eover", newalready.path)); return; } String dpath = (ap.path.equals("/") ? "/" : ap.path+"/")+newname.getText(); RemoteFile nf = filemgr.paste_file(src, already.directory, dpath, newalready, mode); if (filemgr.cut_mode && nf != null) { // Paste from the destination path from now on filemgr.cut_buffer[idx] = nf; } dispose(); } } } class SambaShare { String path; boolean available; boolean writable; int guest; String comment; SambaShare(String l) { StringSplitter tok = new StringSplitter(l, ':'); path = tok.nextToken(); available = tok.nextToken().equals("1"); writable = tok.nextToken().equals("1"); guest = Integer.parseInt(tok.nextToken()); comment = tok.nextToken(); } SambaShare(String p, boolean a, boolean w, int g, String c) { path = p; available = a; writable = w; guest = g; comment = c; } String params() { return "path="+FileManager.urlize(path)+ "&available="+(available ? 1 : 0)+ "&writable="+(writable ? 1 : 0)+ "&guest="+guest+ "&comment="+FileManager.urlize(comment); } } class DFSAdminExport { String path; String desc; String ro, rw, root; DFSAdminExport(String l) { StringSplitter tok = new StringSplitter(l, ':'); path = tok.nextToken(); ro = tok.nextToken(); rw = tok.nextToken(); root = tok.nextToken(); desc = tok.nextToken(); } DFSAdminExport(String p, String d, String ro, String rw, String root) { path = p; desc = d; this.ro = ro; this.rw = rw; this.root = root; } String[] split(String s) { StringTokenizer stok = new StringTokenizer(s, " "); String rv[] = new String[stok.countTokens()]; for(int i=0; i 1)); add_item(name, p, l, r); TextField t = new TextField(v.equals("-") ? "" : v, 25); add_item("", t, l, r); return t; } Choice squashbox(int s) { Choice rv = new Choice(); rv.addItem(filemgr.text("share_s0")); rv.addItem(filemgr.text("share_s1")); rv.addItem(filemgr.text("share_s2")); rv.select(s); return rv; } Choice robox(boolean r) { Choice rv = new Choice(); rv.addItem(filemgr.text("share_lrw")); rv.addItem(filemgr.text("share_lro")); rv.select(r ? 1 : 0); return rv; } Panel opts_panel(Component ro, Component squash) { Panel p = new Panel(); p.setLayout(new BorderLayout()); p.add("West", ro); p.add("East", squash); return p; } void export_options(LinuxExport e) { int c = 0; for(int i=0; i 0) c++; e.host = new String[c]; e.ro = new boolean[c]; e.squash = new int[c]; for(int i=0,j=0; i 0) { e.host[j] = host[i].getText(); e.ro[j] = lro[i].getSelectedIndex() == 1; e.squash[j] = squash[i].getSelectedIndex(); j++; } } } } class SearchWindow extends FixedFrame implements CbButtonCallback,MultiColumnCallback { TabbedPanel tab; MultiColumn list; CbButton search_b, cancel_b; FileManager filemgr; TextField dir, match, user, group; Checkbox uany, usel, gany, gsel; Choice type; Checkbox sany, smore, sless; TextField more, less; Checkbox xon, xoff; String types[] = { "", "f", "d", "l", "p" }; RemoteFile results[]; SearchWindow(String d, FileManager p) { filemgr = p; setTitle(filemgr.text("search_title")); // setup UI setLayout(new BorderLayout()); tab = new TabbedPanel(); Panel search = new Panel(); search.setLayout(new BorderLayout()); tab.addItem(filemgr.text("search_crit"), search); Panel l = new Panel(), r = new Panel(); l.setLayout(new GridLayout(0, 1)); r.setLayout(new GridLayout(0, 1)); String cols[] = { "", filemgr.text("right_name"), filemgr.text("right_size") }; float widths[] = { .07f, .78f, .15f }; list = new MultiColumn(cols, this); list.setWidths(widths); list.setDrawLines(false); tab.addItem(filemgr.text("search_list"), list); add_item(filemgr.text("search_dir"), dir = new TextField(d, 30), l, r); add_item(filemgr.text("search_match"), match = new TextField(20), l, r); Panel up = new Panel(); up.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1)); CheckboxGroup ug = new CheckboxGroup(); up.add(uany = new Checkbox(filemgr.text("search_any"), ug, true)); up.add(usel = new Checkbox("", ug, false)); up.add(user = new TextField(10)); add_item(filemgr.text("search_user"), up, l, r); Panel gp = new Panel(); gp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1)); CheckboxGroup gg = new CheckboxGroup(); gp.add(gany = new Checkbox(filemgr.text("search_any"), gg, true)); gp.add(gsel = new Checkbox("", gg, false)); gp.add(group = new TextField(10)); add_item(filemgr.text("search_group"), gp, l, r); type = new Choice(); for(int i=0; i 0) url += "&type="+types[type.getSelectedIndex()]; if (usel.getState()) { String u = user.getText().trim(); if (u.length() == 0) { new ErrorWindow(filemgr.text("search_euser")); return; } url += "&user="+filemgr.urlize(u); } if (gsel.getState()) { String g = group.getText().trim(); if (g.length() == 0) { new ErrorWindow(filemgr.text("search_egroup")); return; } url += "&group="+filemgr.urlize(g); } if (smore.getState()) { String m = more.getText().trim(); try { Integer.parseInt(m); } catch(Exception e) { new ErrorWindow(filemgr.text("search_esize")); return; } url += "&size=%2B"+m+"c"; } else if (sless.getState()) { String l = less.getText().trim(); try { Integer.parseInt(l); } catch(Exception e) { new ErrorWindow(filemgr.text("search_esize")); return; } url += "&size=%2D"+l+"c"; } if (xon.getState()) url += "&xdev=1"; // send off the search setCursor(WAIT_CURSOR); String f[] = filemgr.get_text(url); if (f[0].length() > 0) { new ErrorWindow(f[0]); return; } Object rows[][] = new Object[f.length-1][]; results = new RemoteFile[f.length-1]; for(int i=1; i= 0) { ACLEntry e = (ACLEntry)acllist.elementAt(idx); ACLEditor ed = (ACLEditor)edmap.get(e); if (ed == null) edmap.put(e, new ACLEditor(this, e)); else { ed.toFront(); ed.requestFocus(); } } } public void singleClick(MultiColumn list, int num) { } public void headingClicked(MultiColumn list, int col) { } } class AttributesWindow extends FixedFrame implements CbButtonCallback,MultiColumnCallback { FileManager filemgr; RemoteFile file; Vector attrlist = new Vector(); Hashtable edmap = new Hashtable(); CbButton ok, cancel, add; MultiColumn attrtable; AttributesWindow(FileManager p, RemoteFile f) { super(400, 300); setTitle(p.text("attr_title", f.path)); filemgr = p; file = f; // Get the attributes String a[] = filemgr.get_text( "getattrs.cgi?file="+filemgr.urlize(file.path)); if (a[0].length() != 0) { new ErrorWindow(filemgr.text("attr_eattrs", a[0])); return; } // Create the UI setLayout(new BorderLayout()); String titles[] = { filemgr.text("attr_name"), filemgr.text("attr_value") }; attrtable = new MultiColumn(titles, this); for(int i=1; i= 0) { FileAttribute at = (FileAttribute)attrlist.elementAt(idx); AttributeEditor ed = (AttributeEditor)edmap.get(at); if (ed == null) edmap.put(at, new AttributeEditor(this, at)); else { ed.toFront(); ed.requestFocus(); } } } public void singleClick(MultiColumn list, int num) { } public void headingClicked(MultiColumn list, int col) { } } class FileAttribute { String name; String value; FileAttribute(String l, FileManager f) { int eq = l.indexOf('='); name = f.un_urlize(l.substring(0, eq)); value = f.un_urlize(l.substring(eq+1)); } FileAttribute(String n, String v) { name = n; value = v; } String[] getRow() { return new String[] { name, value }; } } class AttributeEditor extends FixedFrame implements CbButtonCallback { FileManager filemgr; AttributesWindow attrwin; FileAttribute attr; boolean creating; CbButton ok, del; TextField name; TextArea value; AttributeEditor(AttributesWindow w, FileAttribute a) { attrwin = w; attr = a; filemgr = w.filemgr; creating = false; makeUI(); } AttributeEditor(AttributesWindow w) { attrwin = w; attr = new FileAttribute("", ""); filemgr = w.filemgr; creating = true; makeUI(); } void makeUI() { setTitle(filemgr.text(creating ? "attr_create" : "attr_edit")); setLayout(new BorderLayout()); Panel top = new Panel(); top.setLayout(new GridLayout(1, 2)); top.add(new Label(filemgr.text("attr_name"))); top.add(name = new TextField(attr.name, 20)); add("North", top); Panel mid = new Panel(); mid.setLayout(new GridLayout(1, 2)); mid.add(new Label(filemgr.text("attr_value"))); mid.add(value = new TextArea(attr.value, 5, 20)); add("Center", mid); Panel bot = new Panel(); bot.setLayout(new FlowLayout(FlowLayout.RIGHT)); bot.add(ok = new CbButton(filemgr.get_image("save.gif"), filemgr.text("save"), CbButton.LEFT, this)); if (!creating) bot.add(del = new CbButton(filemgr.get_image("cancel.gif"), filemgr.text("delete"), CbButton.LEFT, this)); add("South", bot); pack(); show(); } public void click(CbButton b) { if (b == ok) { // Update or add the attribute if (name.getText().length() == 0) { new ErrorWindow(filemgr.text("attr_ename")); return; } attr.name = name.getText(); attr.value = value.getText(); if (creating) { // Add to the attribs table attrwin.attrlist.addElement(attr); attrwin.attrtable.addItem(attr.getRow()); } else { // Update the table int idx = attrwin.attrlist.indexOf(attr); attrwin.attrtable.modifyItem(attr.getRow(), idx); } dispose(); } else if (b == del) { // Remove this entry int idx = attrwin.attrlist.indexOf(attr); attrwin.attrlist.removeElementAt(idx); attrwin.attrtable.deleteItem(idx); dispose(); } } public void dispose() { attrwin.edmap.remove(attr); super.dispose(); } } class EXTWindow extends FixedFrame implements CbButtonCallback { FileManager filemgr; RemoteFile file; CbButton ok, cancel; Checkbox cbs[]; String attrs[] = { "A", "a", "c", "d", "i", "s", "S", "u" }; Hashtable attrmap = new Hashtable(); EXTWindow(FileManager p, RemoteFile f) { super(); setTitle(p.text("ext_title", f.path)); filemgr = p; file = f; // Get the attributes String a[] = filemgr.get_text( "getext.cgi?file="+filemgr.urlize(file.path)); if (a[0].length() != 0) { new ErrorWindow(filemgr.text("ext_eattrs", a[0])); return; } for(int i=0; i