import java.awt.*;
import java.awt.event.*;
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, config_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, mount_b, search_b, acl_b,
attr_b, ext_b, preview_b, extract_b, hnew_b;
// Directory tree
Hierarchy dirs;
FileNode root;
Hashtable nodemap = new Hashtable();
// File list
MultiColumn files;
TextField pathname;
CbButton history_b;
RemoteFile showing_files;
RemoteFile showing_list[];
Vector history_list = new Vector();
// 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[];
String accnoroot[];
Hashtable lang = new Hashtable();
Hashtable stab = new Hashtable(),
ntab = new Hashtable();
boolean sambamode;
int nfsmode;
String trust;
String extra;
String images;
int iconsize;
boolean got_filesystems,
acl_support, attr_support, ext_support;
Hashtable mounts = new Hashtable();
Vector fslist = new Vector();
boolean read_only = false;
// Standard font for all text
Font fixed;
// Font for button labels
Font small_fixed;
// Full session cookie
String session;
// HTTP referer
String referer;
// Archive parameter
String archive;
// Chroot directory for tree
String chroot;
// File attributes that can be edited
boolean can_perms, can_users;
// Symlimks are automatically followed
boolean follow_links;
// Can search file contents
boolean search_contents;
// Use text editor for HTML
boolean force_text;
// File extensions to consider as HTML
String htmlexts[];
public void init()
{
setLayout(new BorderLayout());
// Create fonts from specified size
fixed = make_font("fixed", 12);
small_fixed = make_font("small_fixed", 10);
Util.setFont(small_fixed);
StringTokenizer tok = new StringTokenizer(getParameter("root"), " ");
accroot = new String[tok.countTokens()];
for(int i=0; tok.hasMoreTokens(); i++)
accroot[i] = tok.nextToken();
if (getParameter("noroot") != null) {
tok = new StringTokenizer(getParameter("noroot"), " ");
accnoroot = new String[tok.countTokens()];
for(int i=0; tok.hasMoreTokens(); i++)
accnoroot[i] = tok.nextToken();
}
else {
accnoroot = new String[0];
}
trust = getParameter("trust");
session = getParameter("session");
referer = getDocumentBase().toString();
extra = getParameter("extra");
if (extra == null) extra = "";
images = getParameter("images");
if (images == null) images = "images";
iconsize = Integer.parseInt(getParameter("iconsize"));
archive = getParameter("doarchive");
if (archive == null) archive = "0";
chroot = getParameter("chroot");
if (chroot == null) chroot = "/";
String can_perms_str = getParameter("canperms");
can_perms = can_perms_str == null || !can_perms_str.equals("0");
String can_users_str = getParameter("canusers");
can_users = can_users_str == null || !can_users_str.equals("0");
String search_contents_str = getParameter("contents");
search_contents = search_contents_str == null ||
!search_contents_str.equals("0");
String force_text_str = getParameter("force_text");
if (force_text_str != null && force_text_str.equals("1"))
force_text = true;
String htmlexts_str = getParameter("htmlexts");
if (htmlexts_str == null || htmlexts_str.equals(""))
htmlexts_str = ".htm .html";
htmlexts = DFSAdminExport.split(htmlexts_str);
// download language strings
String l[] = get_text("lang.cgi");
if (l.length < 1 || l[0].indexOf('=') < 0) {
String err = "Failed to get language list : "+join_array(l);
new ErrorWindow(err);
throw new Error(err);
}
for(int i=0; i<l.length; i++) {
int eq = l[i].indexOf('=');
if (eq >= 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<s.length; i++) {
SambaShare ss = new SambaShare(s[i]);
stab.put(ss.path, ss);
}
sambamode = true;
}
// list NFS exports
String e[] = get_text("list_exports.cgi");
nfsmode = e.length == 0 ? 0 : Integer.parseInt(e[0]);
if (nfsmode != 0) {
for(int i=1; i<e.length; i++) {
if (nfsmode == 1) {
// Linux export
LinuxExport le = new LinuxExport(e[i]);
ntab.put(le.path, le);
}
else if (nfsmode == 2) {
// Solaris share
DFSAdminExport de = new DFSAdminExport(e[i]);
ntab.put(de.path, de);
}
}
}
// list filesystems
get_filesystems();
// get read-only flag
if (getParameter("ro").equals("1"))
read_only = true;
// get custom colours
Util.light_edge = get_colour("light_edge", Util.light_edge);
Util.dark_edge = get_colour("dark_edge", Util.dark_edge);
Util.body = get_colour("body", Util.body);
Util.body_hi = get_colour("body_hi", Util.body_hi);
Util.light_edge_hi = get_colour("light_edge_hi", Util.light_edge_hi);
Util.dark_edge_hi = get_colour("dark_edge_hi", Util.dark_edge_hi);
Util.dark_bg = get_colour("dark_bg", Util.dark_bg);
Util.text = get_colour("text", Util.text);
Util.light_bg = get_colour("light_bg", Util.light_bg);
// create button panel
BorderPanel top = new BorderPanel(2, Util.body);
top.setLayout(new ToolbarLayout(ToolbarLayout.LEFT, 5, 2));
Panel top1 = new Panel();
top1.setLayout(new GridLayout(1, 0));
if (getParameter("return") != null && can_button("return"))
top1.add(ret_b = make_button("ret.gif", text("top_ret")));
if (getParameter("config") != null && can_button("config"))
top1.add(config_b = make_button("config.gif",
text("top_config")));
if (can_button("save"))
top1.add(down_b = make_button("down.gif", text("top_down")));
if (can_button("preview"))
top1.add(preview_b = make_button("preview.gif", text("top_preview")));
if (!read_only && can_button("edit")) {
top1.add(edit_b = make_button("edit.gif", text("top_edit")));
}
if (can_button("refresh"))
top1.add(refresh_b = make_button("refresh.gif", text("top_refresh")));
if (!read_only && can_button("info"))
top1.add(props_b = make_button("props.gif", text("top_info")));
if (acl_support && !read_only && can_button("acl"))
top1.add(acl_b = make_button("acl.gif", text("top_eacl")));
if (attr_support && !read_only && can_button("attr"))
top1.add(attr_b = make_button("attr.gif", text("top_attr")));
if (ext_support && !read_only && can_button("ext"))
top1.add(ext_b = make_button("ext.gif", text("top_ext")));
if (can_button("search"))
top1.add(search_b = make_button("search.gif", text("top_search")));
top.add(top1);
if (!read_only) {
Panel top2 = new Panel();
top2.setLayout(new GridLayout(1, 0));
if (can_button("delete"))
top2.add(delete_b = make_button("delete.gif",
text("top_delete")));
if (can_button("new")) {
top2.add(new_b = make_button("new.gif",
text("top_new")));
top2.add(hnew_b = make_button("html.gif",
text("top_new")));
}
if (can_button("upload"))
top2.add(upload_b = make_button("upload.gif",
text("top_upload")));
top2.add(extract_b = make_button("extract.gif",
text("top_extract")));
if (can_button("mkdir"))
top2.add(mkdir_b = make_button("mkdir.gif",
text("top_new")));
if (getParameter("follow").equals("0") &&
can_button("makelink"))
top2.add(makelink_b = make_button("makelink.gif",
text("top_new")));
if (can_button("rename"))
top2.add(rename_b = make_button("rename.gif",
text("top_rename")));
if ((sambamode || nfsmode != 0) &&
getParameter("sharing").equals("1") &&
can_button("sharing"))
top2.add(share_b = make_button("share.gif",
text("top_share")));
if (getParameter("mounting").equals("1") &&
can_button("mount"))
top2.add(mount_b = make_button("mount.gif",
text("top_mount")));
top.add(top2);
if (can_button("copy")) {
Panel top3 = new Panel();
top3.setLayout(new GridLayout(1, 0));
top3.add(copy_b = make_button("copy.gif",
text("top_copy")));
top3.add(cut_b = make_button("cut.gif",
text("top_cut")));
top3.add(paste_b = make_button("paste.gif",
text("top_paste")));
top.add(top3);
}
}
add("North", top);
follow_links = getParameter("follow").equals("1");
// create directory tree
BorderPanel left = new BorderPanel(2, Util.body);
left.setLayout(new BorderLayout());
root = new FileNode(new RemoteFile(this, get_text("root.cgi")[0],null));
left.add("Center", dirs = new Hierarchy(root, this));
dirs.setFont(fixed);
root.open = true; root.fill();
// create file list window
BorderPanel right = new BorderPanel(2, Util.body);
right.setLayout(new BorderLayout());
Panel rtop = new Panel();
rtop.setLayout(new BorderLayout());
rtop.add("Center", pathname = new TextField());
rtop.add("East", history_b = new CbButton(text("history_button"),this));
right.add("North", rtop);
pathname.setFont(fixed);
String cols[] = { "", text("right_name"), text("right_size"),
text("right_user"), text("right_group"),
text("right_date") };
float widths[] = { .07f, .33f, .15f, .15f, .15f, .15f };
right.add("Center", files = new MultiColumn(cols, this));
files.setWidths(widths);
files.setDrawLines(false);
files.setMultiSelect(true);
files.setFont(fixed);
show_files(root.file);
ResizePanel mid = new ResizePanel(left, right, .3, false);
add("Center", mid);
// Go to the restricted directory
String home = getParameter("home");
String go = getParameter("goto");
String open = getParameter("open");
if (open != null) {
find_directory(open, true);
}
else if (go != null && go.equals("1")) {
if (home != null)
find_directory(home, true);
else if (!accroot[0].equals("/"))
find_directory(accroot[0], true);
}
}
Font make_font(String name, int defsize)
{
String str = getParameter(name);
int size = str == null || str.equals("") ? defsize :
Integer.parseInt(str);
return new Font("courier", Font.PLAIN, size);
}
// Looks up an applet parameter for a colour, and returns it if
// defined, otherwise the default. MUST be in RRGGBB hex format
Color get_colour(String name, Color def)
{
String str = getParameter("applet_"+name);
if (str == null) {
return def;
}
else {
return new Color(get_hex(str, 0),
get_hex(str, 2),
get_hex(str, 4));
}
}
int get_hex(String str, int pos)
{
str = str.toUpperCase();
char c1 = str.charAt(pos), c2 = str.charAt(pos+1);
int b1 = Character.isDigit(c1) ? c1-48 : c1-65+10;
int b2 = Character.isDigit(c2) ? c2-48 : c2-65+10;
return (b1<<4) + (b2);
}
boolean can_button(String name)
{
return getParameter("no_"+name) == null;
}
CbButton make_button(String f, String t)
{
if (iconsize == 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);
}
// Gets charset parameter from Content-Type: header
String get_charset(String ct)
{
if (ct == null)
return null;
StringTokenizer st = new StringTokenizer(ct, ";");
while (st.hasMoreTokens()) {
String l = st.nextToken().trim();
if (l.startsWith("charset=")) {
// get the value of charset= param.
return l.substring(8);
}
}
return null;
}
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 += extra;
URL u = new URL(getDocumentBase(), url);
URLConnection uc = u.openConnection();
set_cookie(uc);
String charset = get_charset(uc.getContentType());
InputStream ris = uc.getInputStream();
BufferedReader is = null;
if (charset == null) {
is = new BufferedReader(new InputStreamReader(ris));
}
else {
// Try to use a character set, and handle failure
try {
is = new BufferedReader(
new InputStreamReader(ris, charset));
}
catch(Exception e) {
e.printStackTrace();
is = new BufferedReader(
new InputStreamReader(ris));
}
}
Vector lv = new Vector();
while(true) {
String l = is.readLine();
if (l == null) { break; }
lv.addElement(l);
}
is.close();
String rv[] = new String[lv.size()];
lv.copyInto(rv);
return rv;
}
catch(Exception e) {
e.printStackTrace();
//return null;
String err[] = { e.getClass().getName()+" : "+e.getMessage() };
return err;
}
}
void set_cookie(URLConnection conn)
{
if (session != null)
conn.setRequestProperty("Cookie", session);
conn.setRequestProperty("Referer", referer);
}
// 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<fl.length; i++) {
Object row[] = rows[i+1] = new Object[6];
if (fl[i].shared() && fl[i].mounted())
row[0] = get_image("smdir.gif");
else if (fl[i].shared() && fl[i].mountpoint())
row[0] = get_image("sudir.gif");
else if (fl[i].shared())
row[0] = get_image("sdir.gif");
else if (fl[i].mounted())
row[0] = get_image("mdir.gif");
else if (fl[i].mountpoint())
row[0] = get_image("udir.gif");
else
row[0] = get_image(RemoteFile.tmap[fl[i].type]);
row[1] = fl[i].name;
if (fl[i].size < 1000)
row[2] = spad(fl[i].size, 5)+" B";
else if (fl[i].size < 1000000)
row[2] = spad(fl[i].size/1000, 5)+" kB";
else
row[2] = spad(fl[i].size/1000000, 5)+" MB";
row[3] = fl[i].user;
row[4] = fl[i].group;
Date d = new Date(fl[i].modified);
//if (now - fl[i].modified < 24*60*60*1000) {
if (n.getDate() == d.getDate() &&
n.getMonth() == d.getMonth() &&
n.getYear() == d.getYear()) {
// show as hour:min
row[5] = pad(d.getHours(),2)+":"+
pad(d.getMinutes(),2);
}
//else if (now - fl[i].modified < 24*60*60*365*1000) {
else if (n.getYear() == d.getYear()) {
// show as day/mon
row[5] = pad(d.getDate(),2)+"/"+
monmap[d.getMonth()];
}
else {
// show as mon/year
row[5] = monmap[d.getMonth()]+"/"+
pad(d.getYear()%100, 2);
}
}
files.addItems(rows);
showing_files = f;
showing_list = fl;
pathname.setText(f.path);
return true;
}
String pad(int n, int s)
{
String rv = String.valueOf(n);
while(rv.length() < s)
rv = "0"+rv;
return rv;
}
String spad(long n, int s)
{
String rv = String.valueOf(n);
while(rv.length() < s)
rv = " "+rv;
return rv;
}
String trim_path(String p)
{
while(p.endsWith("/"))
p = p.substring(0, p.length()-1);
return p;
}
// openNode
// Called when a node with children is opened
public void openNode(Hierarchy h, HierarchyNode n)
{
FileNode fn = (FileNode)n;
fn.fill();
}
// closeNode
// Called when a node is closed
public void closeNode(Hierarchy h, HierarchyNode n)
{
}
// clickNode
// Called when the user clicks on a node
public void clickNode(Hierarchy h, HierarchyNode n)
{
FileNode fn = (FileNode)n;
if (showing_files != fn.file)
show_files(fn.file);
}
// doubleNode
// Called when a user double-clicks on a node
public void doubleNode(Hierarchy h, HierarchyNode n)
{
}
// Called when a button is clicked
public void click(CbButton b)
{
int s = files.selected();
int ss[] = files.allSelected();
RemoteFile f = null, ff[] = new RemoteFile[0];
if (s > 0 || s == 0 && ss.length > 1) {
// At least one non-.. file was selected
boolean parentsel = false;
for(int i=0; i<ss.length; i++)
if (ss[i] == 0)
parentsel = true;
RemoteFile list[] = showing_list;
if (parentsel) {
// need to exclude .. from selected list!
ff = new RemoteFile[ss.length-1];
for(int i=0,j=0; i<ss.length; i++)
if (ss[i] != 0)
ff[j++] = list[ss[i]-1];
f = s == 0 ? ff[0] : list[s-1];
}
else {
// include all selected files
f = list[s-1];
ff = new RemoteFile[ss.length];
for(int i=0; i<ss.length; i++)
ff[i] = list[ss[i]-1];
}
}
FileNode d = (FileNode)dirs.selected();
if (b == ret_b) {
// Return to the webmin index
try {
URL u = new URL(getDocumentBase(),
getParameter("return"));
getAppletContext().showDocument(u);
}
catch(Exception e) { }
}
else if (b == config_b) {
// Open the module config window
try {
URL u = new URL(getDocumentBase(),
getParameter("config"));
getAppletContext().showDocument(u, "_self");
}
catch(Exception e) { }
}
else if (b == edit_b) {
// Open a window for editing the selected file
if (f == null)
new ErrorWindow(text("top_efile"));
else if (f.type == 0 || f.type > 4)
new ErrorWindow(text("edit_enormal"));
else if (is_html_filename(f.path) && !force_text) {
// Open HTML editor
try {
JSObject win = JSObject.getWindow(this);
String params[] = { f.path, "" };
win.call("htmledit", params);
}
catch(Exception e) {
new ErrorWindow(text("html_efailed",
e.getMessage()));
}
}
else {
// Open text editor
new EditorWindow(f, this);
}
}
else if (b == down_b) {
// Force download of the selected file
if (f == null) return;
download_file(f);
}
else if (b == preview_b) {
// Open preview window for selected file
if (f == null) return;
if (f.type == RemoteFile.DIR)
new ErrorWindow(text("preview_eimage"));
else
new PreviewWindow(this, f);
}
else if (b == refresh_b) {
// Refesh the selected directory (and thus any subdirs)
if (d == null) return;
d.refresh();
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<cut_buffer.length; i++) {
RemoteFile cf = cut_buffer[i];
// Check for an existing file
RemoteFile already = showing_files.find(cf.name);
String sp = showing_files.path;
String dest_path = sp.equals("/") ? sp+cf.name
: sp+"/"+cf.name;
if (already != null) {
// File exists .. offer to rename
new OverwriteWindow(this, already, cf, i);
}
else {
// do the move or copy
RemoteFile nf = paste_file(cf, showing_files,
dest_path, null, cut_mode);
if (cut_mode && nf != null) {
// Paste from the destination path
// from now on
cut_buffer[i] = nf;
}
}
}
cut_mode = false;
}
else if (b == delete_b) {
// Delete the selected files
if (f == null) return;
new DeleteWindow(this, ff);
}
else if (b == new_b) {
// Open a window for creating a text file
new EditorWindow(showing_files.path, this);
}
else if (b == hnew_b) {
// Open a window for creating an HTML file
try {
JSObject win = JSObject.getWindow(this);
String params[] = { "", showing_files.path };
win.call("htmledit", params);
}
catch(Exception e) {
new ErrorWindow(text("html_efailed",
e.getMessage()));
}
}
else if (b == upload_b) {
// Call javascript to open an upload window
try {
JSObject win = JSObject.getWindow(this);
String params[] = { showing_files.path };
win.call("upload", params);
}
catch(Exception e) {
new ErrorWindow(text("upload_efailed", e.getMessage()));
}
}
else if (b == extract_b) {
// Ask for confirmation, then extract file
if (f == null) return;
if (f.type == 0 || f.type == 6 || f.type == 7)
new ErrorWindow(text("extract_etype", f.path));
else
new ExtractWindow(this, f);
}
else if (b == mkdir_b) {
// Prompt for new directory
new MkdirWindow(showing_files.path, this);
}
else if (b == makelink_b) {
// Prompt for a new symlink
new LinkWindow(showing_files.path, this);
}
else if (b == rename_b) {
// Prompt for new filename
if (f == null) return;
new RenameWindow(this, f);
}
else if (b == share_b) {
// Open a window for editing sharing options
if (f == null || f.type != RemoteFile.DIR) return;
new SharingWindow(f, this);
}
else if (b == mount_b) {
// Check if the selected directory is a mount point
if (f == null || f.type != RemoteFile.DIR) return;
FileSystem fs = f.fs();
if (fs == null)
new ErrorWindow(text("mount_epoint", f.path));
else
new MountWindow(this, fs, f);
}
else if (b == search_b) {
// Open window for finding a file
new SearchWindow(showing_files.path, this);
}
else if (b == history_b) {
// Open entered file history window
if (history_list.size() > 0) {
new HistoryWindow(this);
}
}
}
boolean is_html_filename(String path)
{
for(int i=0; i<htmlexts.length; i++)
if (path.toLowerCase().endsWith(htmlexts[i]))
return true;
return false;
}
boolean under_root_dir(String p, String roots[])
{
boolean can = false;
int l = p.length();
for(int r=0; r<roots.length; r++) {
int rl = roots[r].length();
if (roots[r].equals("/"))
can = true;
else if (l >= rl && p.substring(0, rl).equals(roots[r]))
can = true;
else if (l < rl && roots[r].substring(0, l).equals(p))
can = true;
}
return can;
}
// Download some file to the user's browser, if possible
void download_file(RemoteFile f)
{
if (f.type == RemoteFile.DIR && !archive.equals("0"))
new DownloadDirWindow(this, f);
else if (f.type == RemoteFile.DIR || f.type > 4)
new ErrorWindow(text("view_enormal2"));
else
open_file_window(f, true, 0);
}
// Returns the object for some directory, or null if not found.
RemoteFile find_directory(String p, boolean fill)
{
boolean can = under_root_dir(p, accroot) &&
!under_root_dir(p, accnoroot);
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<fl.length; i++)
if (fl[i].name.equals(fn)) {
pos = fl[i];
found = true;
}
if (!found) {
new ErrorWindow(text("find_eexist", fn, p));
return null;
}
if (pos.type != 0) {
new ErrorWindow(text("find_edir", fn, p));
return null;
}
if (fill)
posnode = (FileNode)nodemap.get(pos);
}
if (fill) {
if (show_files(pos)) {
posnode.fill();
posnode.open = true;
dirs.select(posnode);
dirs.redraw();
}
}
return pos;
}
FileSystem find_filesys(RemoteFile f)
{
FileSystem filefs = null;
for(int i=0; i<fslist.size(); i++) {
FileSystem fs = (FileSystem)fslist.elementAt(i);
int l = fs.mount.length();
if (fs.mount.equals(f.path) ||
(f.path.length() >= 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);
// Add to the history
if (!history_list.contains(p)) {
history_list.insertElementAt(p, 0);
}
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
open_file_window(d, list.last_event.shiftDown(), 0);
}
}
// 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<ss.length; i++)
ssf[i] = showing_list[ss[i]-1];
show_files(showing_files);
for(int i=0; i<ss.length; i++) {
for(int j=0; j<showing_list.length; j++) {
if (showing_list[j] == ssf[i]) {
ss[i] = j+1;
break;
}
}
}
files.select(ss);
}
void open_file_window(RemoteFile f, boolean download, int format)
{
try {
String ext = format == 1 ? ".zip" :
format == 2 ? ".tgz" :
format == 3 ? ".tar" : "";
String urlstr;
if (download) {
urlstr = "show.cgi"+urlize(f.path)+ext+
"?rand="+System.currentTimeMillis()+
"&type=application%2Funknown"+
"&trust="+trust+
"&format="+format+
extra;
}
else {
urlstr = "show.cgi"+urlize(f.path)+ext+
"?rand="+System.currentTimeMillis()+
"&trust="+trust+
"&format="+format+
extra;
}
// Do a test fetch
String l[] = get_text(urlstr+"&test=1");
if (l[0].length() > 0) {
new ErrorWindow(text("eopen", l[0]));
return;
}
// Open for real
if (download) {
getAppletContext().showDocument(
new URL(getDocumentBase(), urlstr));
}
else {
getAppletContext().showDocument(
new URL(getDocumentBase(), urlstr), "show");
}
}
catch(Exception e) { }
}
static String urlize(String s)
{
StringBuffer rv = new StringBuffer();
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c < 16)
rv.append("%0"+Integer.toString(c, 16));
else if ((!Character.isLetterOrDigit(c) && c != '/' &&
c != '.' && c != '_' && c != '-') || c >= 128)
rv.append("%"+Integer.toString(c, 16));
else
rv.append(c);
}
return rv.toString();
}
static String un_urlize(String s)
{
StringBuffer rv = new StringBuffer();
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c == '%') {
rv.append((char)Integer.parseInt(
s.substring(i+1, i+3), 16));
i += 2;
}
else
rv.append(c);
}
return rv.toString();
}
// Called back by Javascript when a file or directory has been modified
public void upload_notify(String path_str, String info)
{
int sl = path_str.lastIndexOf('/');
String par_str = path_str.substring(0, sl),
file_str = path_str.substring(sl+1);
RemoteFile par = find_directory(par_str, false);
RemoteFile upfile = par.find(file_str);
try {
if (upfile == null) {
// Need to add this file/directory
upfile = new RemoteFile(this, info, par);
par.add(upfile);
}
else if (upfile.type == RemoteFile.DIR) {
// Is a directory .. refresh from server
FileNode upnode = (FileNode)nodemap.get(upfile);
if (upnode != null)
upnode.refresh();
}
show_files(showing_files);
}
catch(Exception e) {
// In some cases, any attempt to make an HTTP request to
// refresh the directory may fail because Java apparently has
// some security rules that limit what a function called from
// JavaScript is allowed to do. All we can do is ignore the
// exception :-(
e.printStackTrace();
}
}
// Called back by Javascript to show an upload-related error
public void upload_error(String err)
{
new ErrorWindow(err);
}
public String text(String k, String p[])
{
String rv = (String)lang.get(k);
if (rv == null) rv = "???";
for(int i=0; i<p.length; i++) {
int idx = rv.indexOf("$"+(i+1));
if (idx != -1)
rv = rv.substring(0, idx)+p[i]+rv.substring(idx+2);
}
return rv;
}
public String text(String k)
{
String p[] = { };
return text(k, p);
}
public String text(String k, String p1)
{
String p[] = { p1 };
return text(k, p);
}
public String text(String k, String p1, String p2)
{
String p[] = { p1, p2 };
return text(k, p);
}
RemoteFile paste_file(RemoteFile src, RemoteFile dir,
String dest, RemoteFile already, boolean mode)
{
// Move or copy the actual file
String[] rv = get_text((mode ? "move.cgi" : "copy.cgi")+
"?from="+urlize(src.path)+
"&to="+urlize(dest));
if (rv[0].length() > 0) {
new ErrorWindow(text(
mode ? "paste_emfailed" : "paste_ecfailed", rv[0]));
return null;
}
RemoteFile file = new RemoteFile(this, rv[1], dir);
if (already == null) {
// Add to the parent directory
dir.add(file);
}
else {
// Update the existing file
already.type = file.type;
already.user = file.user;
already.group = file.group;
already.size = file.size;
already.perms = file.perms;
already.modified = file.modified;
file = already;
}
if (mode) {
// Delete the old file
src.directory.delete(src);
}
if (src.type == 0) {
// Moving or copying a directory.. update the tree
FileNode dest_par_node =
(FileNode)nodemap.get(showing_files);
dest_par_node.add(new FileNode(file));
if (mode) {
FileNode cut_par_node =
(FileNode)nodemap.get(src.directory);
FileNode cut_file_node =
(FileNode)nodemap.get(src);
if (cut_par_node != null &&
cut_file_node != null)
cut_par_node.ch.removeElement(
cut_file_node);
}
dirs.redraw();
}
show_files(showing_files);
return file;
}
// Loads the list of filesystems from the server, and refreshes all
// caches
void get_filesystems()
{
String f[] = get_text("filesystems.cgi");
got_filesystems = f[0].equals("1");
acl_support = false;
attr_support = false;
ext_support = false;
mounts.clear();
fslist.removeAllElements();
if (got_filesystems) {
for(int i=1; i<f.length; i++) {
FileSystem fs = new FileSystem(f[i]);
fslist.addElement(fs);
if (fs.acls) acl_support = true;
if (fs.attrs) attr_support = true;
if (fs.ext) ext_support = true;
mounts.put(fs.mount, fs);
}
}
}
String join_array(String l[])
{
String rv = "";
for(int i=0; i<l.length; i++)
rv += l[i]+"\n";
return rv;
}
static String replace_str(String str, String os, String ns)
{
String rv;
int idx;
int pos = 0;
rv = str;
while((idx = rv.indexOf(os, pos)) >= 0) {
rv = rv.substring(0, idx)+
ns+rv.substring(idx+os.length());
pos = idx+ns.length()+1;
}
return rv;
}
}
// A node in the directory tree
class FileNode extends HierarchyNode
{
FileManager parent;
RemoteFile file;
boolean known;
FileNode(RemoteFile file)
{
this.file = file;
parent = file.parent;
setimage();
ch = new Vector();
text = file.name;
parent.nodemap.put(file, this);
}
// Create the nodes for subdirectories
void fill()
{
if (!known) {
RemoteFile l[] = file.list();
if (l == null) return;
ch.removeAllElements();
for(int i=0; i<l.length; i++)
if (l[i].type == 0)
ch.addElement(new FileNode(l[i]));
parent.dirs.redraw();
known = true;
}
}
void add(FileNode n)
{
for(int i=0; i<=ch.size(); i++) {
FileNode ni = i==ch.size() ? null : (FileNode)ch.elementAt(i);
if (ni == null || ni.text.compareTo(n.text) > 0) {
ch.insertElementAt(n, i);
break;
}
}
}
void setimage()
{
im = parent.get_image(file.shared() && file.mounted() ? "smdir.gif" :
file.shared() && file.mountpoint() ? "sudir.gif" :
file.shared() ? "sdir.gif" :
file.mounted() ? "mdir.gif" :
file.mountpoint() ? "udir.gif" :
"dir.gif");
}
// Forces a re-load from the server
void refresh()
{
known = false;
file.list = null;
fill();
}
}
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");
if (tok.countTokens() < 7) {
String err = "Invalid file line : "+line;
new ErrorWindow(err);
throw new Error(err);
}
path = tok.nextToken();
path = parent.replace_str(path, "\\t", "\t");
path = parent.replace_str(path, "\\\\", "\\");
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<l.length; i++)
list[i-3] = new RemoteFile(parent, l[i], this);
}
}
return list;
}
RemoteFile find(String n)
{
RemoteFile l[] = list();
if (l != null) {
for(int i=0; i<l.length; i++)
if (l[i].name.equals(n))
return l[i];
}
return null;
}
void add(RemoteFile f)
{
RemoteFile nlist[] = new RemoteFile[list.length+1];
int offset = 0;
for(int i=0; i<list.length; i++) {
if (list[i].name.compareTo(f.name) > 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<list.length; i++)
if (list[i] != f)
nlist[j++] = list[i];
list = nlist;
}
boolean shared()
{
return type == DIR &&
(parent.stab.get(path) != null ||
parent.ntab.get(path) != null);
}
boolean mountpoint()
{
return type == DIR && fs() != null;
}
boolean mounted()
{
FileSystem fs = fs();
return type == DIR && fs != null && fs.mtab;
}
FileSystem fs()
{
return (FileSystem)parent.mounts.get(path);
}
}
class EditorWindow extends FixedFrame implements CbButtonCallback
{
TextField name;
TextArea edit;
CbButton save_b, saveclose_b, cancel_b, goto_b, find_b;
Checkbox dosmode;
RemoteFile file;
FileManager filemgr;
GotoWindow goto_window;
FindReplaceWindow find_window;
String charset;
// Editing an existing file
EditorWindow(RemoteFile f, FileManager p)
{
super(800, 600);
file = f; filemgr = p;
makeUI(false);
setTitle(filemgr.text("edit_title", file.path));
// Load the file
try {
URL u = new URL(filemgr.getDocumentBase(),
"show.cgi"+filemgr.urlize(file.path)+
"?rand="+System.currentTimeMillis()+
"&trust="+filemgr.trust+"&edit=1"+
filemgr.extra);
URLConnection uc = u.openConnection();
filemgr.set_cookie(uc);
int len = uc.getContentLength();
InputStream is = uc.getInputStream();
charset = filemgr.get_charset(uc.getContentType());
byte buf[];
if (len >= 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;
}
}
String s = charset == null ? new String(buf, 0)
: new String(buf, charset);
if (s.indexOf("\r\n") != -1) {
dosmode.setState(true);
s = FileManager.replace_str(s, "\r\n", "\n");
}
edit.setText(s);
is.close();
file.size = buf.length;
}
catch(Exception e) { e.printStackTrace(); }
}
// Creating a new file
EditorWindow(String f, FileManager p)
{
super(800, 600);
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());
name.setFont(filemgr.fixed);
add("North", np);
}
add("Center", edit = new TextArea(20, 80));
edit.setFont(filemgr.fixed);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(dosmode = new Checkbox("Windows newlines"));
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(saveclose_b = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("edit_saveclose"),
CbButton.LEFT, this));
bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("close"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == save_b || b == saveclose_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;
s = FileManager.replace_str(s, "\r\n", "\n");
try {
if (dosmode.getState()) {
// Convert to DOS newlines
s = FileManager.replace_str(s, "\n", "\r\n");
}
else {
// Remove any DOS newlines
s = FileManager.replace_str(s, "\r\n", "\n");
}
URL u = new URL(filemgr.getDocumentBase(),
"save.cgi"+filemgr.urlize(save_path)+
"?rand="+System.currentTimeMillis()+
"&trust="+filemgr.trust+
"&length="+s.length()+
filemgr.extra);
URLConnection uc = u.openConnection();
uc.setRequestProperty("Content-type", "text/plain");
filemgr.set_cookie(uc);
uc.setDoOutput(true);
OutputStream os = uc.getOutputStream();
byte buf[];
if (charset == null) {
// Assume ascii
buf = new byte[s.length()];
s.getBytes(0, buf.length, buf, 0);
}
else {
// Convert back to original charset
buf = s.getBytes(charset);
}
os.write(buf);
os.close();
BufferedReader is =
new BufferedReader(new InputStreamReader(
uc.getInputStream()));
String err = is.readLine();
if (err.length() > 0) {
new ErrorWindow(
filemgr.text("edit_esave", err));
is.close();
return;
}
line = is.readLine();
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);
if (b == saveclose_b)
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));
line.setFont(filemgr.fixed);
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);
Util.recursiveBody(this);
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<txt.length(); c++) {
if (txt.charAt(c) == '\n') {
l++;
if (l == lnum) {
// Found the line!
editor.edit.select(c, c);
dispose();
editor.edit.requestFocus();
return;
}
}
}
}
else if (b == cancel_b) {
// Just close the window
dispose();
}
}
public void dispose()
{
super.dispose();
editor.goto_window = null;
}
public boolean handleEvent(Event e)
{
if (e.target == line && e.id == Event.KEY_RELEASE && e.key == 10) {
click(goto_b);
return true;
}
return false;
}
}
class FindReplaceWindow extends FixedFrame implements CbButtonCallback
{
EditorWindow editor;
FileManager filemgr;
TextField find, replace;
CbButton find_b, replace_b, all_b, cancel_b;
FindReplaceWindow(EditorWindow e)
{
editor = e;
filemgr = e.filemgr;
setLayout(new BorderLayout());
Panel left = new Panel();
left.setLayout(new GridLayout(2, 1));
left.add(new Label(filemgr.text("edit_searchfor")));
left.add(new Label(filemgr.text("edit_replaceby")));
add("West", left);
Panel right = new Panel();
right.setLayout(new GridLayout(2, 1));
right.add(find = new TextField(40));
find.setFont(filemgr.fixed);
right.add(replace = new TextField(40));
replace.setFont(filemgr.fixed);
add("Center", right);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(find_b = new CbButton(filemgr.get_image("find.gif"),
filemgr.text("edit_find"),
CbButton.LEFT, this));
bot.add(replace_b = new CbButton(filemgr.get_image("replace.gif"),
filemgr.text("edit_replace"),
CbButton.LEFT, this));
bot.add(all_b = new CbButton(filemgr.get_image("all.gif"),
filemgr.text("edit_all"),
CbButton.LEFT, this));
bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("close"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
String findtxt = find.getText();
String edittxt = editor.edit.getText();
if (findtxt.length() == 0)
return;
if (b == find_b) {
// Find the next occurrance of the text, starting from
// the cursor + 1, and select it
int pos = edittxt.indexOf(findtxt,
editor.edit.getSelectionStart()+1);
if (pos < 0) {
// Not found .. but try wrap-around
pos = edittxt.indexOf(findtxt, 0);
}
if (pos < 0)
new ErrorWindow(filemgr.text("edit_notfound", findtxt));
else {
editor.edit.select(pos, pos+findtxt.length());
editor.edit.requestFocus();
}
}
else if (b == replace_b) {
// If the word to search for is selected, replace it. Otherwise
// just search for the next one
int st = editor.edit.getSelectionStart(),
en = editor.edit.getSelectionEnd();
if (st >= 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, size_b;
TextField linkto;
TextField user, group;
Checkbox setuid, setgid;
PermissionsPanel user_p, group_p, other_p;
Checkbox sticky;
Choice rec_mode;
TextField octal;
TextField bytes, files, dirs;
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));
if (file.type == 0) {
bot.add(size_b = new CbButton(filemgr.get_image("refresh.gif"),
filemgr.text("info_getsize"),
CbButton.LEFT, this));
}
if (filemgr.can_perms || filemgr.can_users) {
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);
linkto.setFont(filemgr.fixed);
}
mid = add_panel(mid, det);
if (filemgr.can_perms) {
// 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.setFont(filemgr.fixed);
octal.setEditable(false);
mid = add_panel(mid, per);
}
if (filemgr.can_users) {
// 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);
user.setFont(filemgr.fixed);
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);
group.setFont(filemgr.fixed);
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 directory size section, initially empty
Panel szp = new LinedPanel(filemgr.text("info_sizeheader")),
sl = new Panel(), sr = new Panel();
setup_leftright(szp, sl, sr);
add_item(filemgr.text("info_bytes"),
bytes = new TextField("", 10), sl, sr);
bytes.setFont(filemgr.fixed);
bytes.setEditable(false);
add_item(filemgr.text("info_files"),
files = new TextField("", 10), sl, sr);
files.setFont(filemgr.fixed);
files.setEditable(false);
add_item(filemgr.text("info_dirs"),
dirs = new TextField("", 10), sl, sr);
dirs.setFont(filemgr.fixed);
dirs.setEditable(false);
mid = add_panel(mid, szp);
}
if (file.type == 0 && (filemgr.can_perms || filemgr.can_users)) {
// 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();
Util.recursiveBody(this);
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();
String user_str = user != null ? user.getText() : null;
String group_str = group != null ? group.getText() : null;
int rec = 0;
if (file.type == 0 && rec_mode != null)
rec = rec_mode.getSelectedIndex();
String rv[] = filemgr.get_text(
"chmod.cgi?path="+filemgr.urlize(file.path)+
(perms < 0 ? "" : "&perms="+perms)+
(user_str == null ? "" :
"&user="+filemgr.urlize(user_str))+
(group_str == null ? "" :
"&group="+filemgr.urlize(group_str))+
"&rec="+rec+
(linkto==null ? "" :
"&linkto="+filemgr.urlize(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 if (b == size_b) {
// Get the size of the directory recursively
String l[] = filemgr.get_text("size.cgi?dir="+
filemgr.urlize(file.path));
if (l[0].length() > 0) {
new ErrorWindow(filemgr.text("info_size", l[0]));
}
StringTokenizer tok = new StringTokenizer(l[1], " ");
String bytes_str = tok.nextToken();
files.setText(tok.nextToken());
dirs.setText(tok.nextToken());
bytes.setText(tok.nextToken()+" "+tok.nextToken());
}
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<f.list.length; i++) {
RemoteFile ff = f.list[i];
if (ff.type == 5) continue;
else if (ff.type == 0) {
if (do_subs) {
update_file(ff, perms, false);
recurse_files(ff, perms, true);
}
}
else update_file(ff, perms, true);
}
}
void setup_leftright(Panel m, Panel l, Panel r)
{
m.setLayout(new BorderLayout());
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West", l);
p.add("Center", r);
l.setLayout(new GridLayout(0, 1));
r.setLayout(new GridLayout(0, 1));
m.add("North", p);
}
void add_item(String t, Component c, Panel l, Panel r)
{
l.add(new Label(t));
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West", c);
r.add(p);
}
void set_octal()
{
if (octal != null) {
String oct = Integer.toOctalString(get_perms());
while(oct.length() < 4)
oct = "0"+oct;
octal.setText(oct);
}
}
int get_perms()
{
if (user_p == null)
return -1; // Cannot edit
int perms = 0;
if (setuid == null)
perms |= (file.perms & 0x800);
else
perms |= (setuid.getState() ? 0x800 : 0);
perms |= (setgid.getState() ? 0x400 : 0);
perms |= user_p.getPerms();
perms |= group_p.getPerms();
perms |= other_p.getPerms();
if (sticky == null)
perms |= (file.perms & 01000);
else
perms |= (sticky.getState() ? 01000 : 0);
return perms;
}
public boolean handleEvent(Event e)
{
if (e.target instanceof Checkbox) {
set_octal();
return true;
}
return super.handleEvent(e);
}
}
class PermissionsPanel extends Panel
{
Checkbox read, write, exec;
int base;
PermissionsPanel(RemoteFile file, int base, FileManager filemgr)
{
int perms = file.perms;
this.base = base;
setLayout(new GridLayout(1, 3));
add(read = new Checkbox(filemgr.text("info_read")));
read.setState((perms&(base<<2)) != 0);
add(write = new Checkbox(filemgr.text("info_write")));
write.setState((perms&(base<<1)) != 0);
add(exec = new Checkbox(
filemgr.text(file.type == RemoteFile.DIR ? "info_list"
: "info_exec")));
exec.setState((perms&base) != 0);
}
int getPerms()
{
int rv = 0;
rv |= (read.getState() ? (base<<2) : 0);
rv |= (write.getState() ? (base<<1) : 0);
rv |= (exec.getState() ? base : 0);
return rv;
}
}
class DeleteWindow extends FixedFrame implements CbButtonCallback
{
CbButton delete_b, cancel_b;
FileManager filemgr;
RemoteFile files[];
DeleteWindow(FileManager p, RemoteFile ff[])
{
filemgr = p;
files = ff;
setTitle(filemgr.text(ff.length > 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<ff.length; i++)
mp.add(new Label(ff[i].path));
add("Center", mp);
}
else
add("Center", new MultiLabel(filemgr.text(
ff[0].type == 0 ? "delete_ddesc" : "delete_fdesc",
ff[0].path), 35));
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.CENTER));
bot.add(delete_b = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("delete"),
CbButton.LEFT, this));
bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == delete_b) {
// Delete the file or directory
boolean need_redraw = false, need_reshow = false;
for(int i=0; i<files.length; i++) {
RemoteFile file = files[i];
String rv[] = filemgr.get_text("delete.cgi?file="+
filemgr.urlize(file.path));
if (rv[0].length() > 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.setFont(filemgr.fixed);
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);
Util.recursiveBody(this);
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.setFont(filemgr.fixed);
from.select(from.getText().length(), from.getText().length());
r.add(to = new TextField());
to.setFont(filemgr.fixed);
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);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == create_b) {
// Check inputs
String from_str = from.getText().trim();
if (!from_str.startsWith("/")) {
new ErrorWindow(filemgr.text("link_efrom", from_str));
return;
}
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);
oldname.setFont(filemgr.fixed);
r.add(newname = new TextField(file.name, 20));
newname.select(file.name.length(), file.name.length());
newname.setFont(filemgr.fixed);
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();
Util.recursiveBody(this);
}
public void click(CbButton b)
{
if (b == rename_b) {
// Work out destination file and directory
String newstr = newname.getText().trim();
if (newstr.length() == 0) return;
RemoteFile destdir;
String newpath;
if (newstr.indexOf('/') >= 0) {
// Different dir
if (newstr.startsWith("/")) {
// Some absolute path
newpath = newstr;
}
else {
// Relative to this dir
newpath = file.directory.path+"/"+newstr;
}
int sl = newpath.lastIndexOf('/');
String newdir = sl == 0 ? "/" : newpath.substring(0,sl);
destdir = filemgr.find_directory(newdir, false);
}
else {
// Same dir
destdir = file.directory;
int sl = file.path.lastIndexOf('/');
newpath = file.path.substring(0, sl)+"/"+newstr;
}
// Work out filename only
int sl = newpath.lastIndexOf('/');
newstr = newpath.substring(sl+1);
// Check for an existing file
RemoteFile already = destdir.find(newstr);
if (already != null) {
new ErrorWindow(filemgr.text("rename_eexists", newstr));
return;
}
// Rename the real file
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);
destdir.list();
destdir.add(file);
file.directory = destdir;
file.list = null;
FileNode parnode = (FileNode)filemgr.nodemap.get(file.directory);
FileNode filenode = (FileNode)filemgr.nodemap.get(file);
if (parnode != null && filenode != null) {
// Need to refresh tree
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 OverwriteWindow extends FixedFrame implements CbButtonCallback
{
FileManager filemgr;
RemoteFile src, already;
TextField newname;
CbButton ok, cancel;
int idx;
boolean mode;
OverwriteWindow(FileManager p, RemoteFile a, RemoteFile s, int i)
{
filemgr = p; src = s; already = a; idx = i;
mode = filemgr.cut_mode;
setLayout(new BorderLayout());
setTitle(filemgr.text("over_title"));
add("North",
new MultiLabel(filemgr.text("over_msg", already.path), 30, 0));
add("West", new Label(filemgr.text("over_new")));
add("East", newname = new TextField(a.name, 30));
newname.setFont(filemgr.fixed);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(ok = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("over_ok"),
CbButton.LEFT, this));
bot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == cancel)
dispose();
else if (b == ok && newname.getText().length() > 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;
}
static String[] split(String s)
{
StringTokenizer stok = new StringTokenizer(s, " ");
String rv[] = new String[stok.countTokens()];
for(int i=0; i<rv.length; i++)
rv[i] = stok.nextToken();
return rv;
}
String params()
{
return "path="+FileManager.urlize(path)+
"&ro="+FileManager.urlize(ro)+
"&rw="+FileManager.urlize(rw)+
"&root="+FileManager.urlize(root)+
"&desc="+FileManager.urlize(desc);
}
}
class LinuxExport
{
String path;
String host[];
boolean ro[];
int squash[];
LinuxExport(String l)
{
StringSplitter tok = new StringSplitter(l, ':');
path = tok.nextToken();
int c = tok.countTokens() / 3;
host = new String[c];
ro = new boolean[c];
squash = new int[c];
for(int i=0; tok.hasMoreTokens(); i++) {
host[i] = tok.nextToken();
ro[i] = tok.nextToken().equals("1");
squash[i] = Integer.parseInt(tok.nextToken());
}
}
LinuxExport(String p, String h[], String r[], String s[])
{
path = p;
}
String params()
{
String rv = "path="+FileManager.urlize(path)+
"&count="+host.length;
for(int i=0; i<host.length; i++) {
rv += "&host"+i+"="+FileManager.urlize(host[i]);
rv += "&ro"+i+"="+(ro[i] ? 1 : 0);
rv += "&squash"+i+"="+squash[i];
}
return rv;
}
}
class SharingWindow extends FixedFrame implements CbButtonCallback
{
CbButton save_b, cancel_b;
RemoteFile file;
FileManager filemgr;
SambaShare sshare;
DFSAdminExport dexport;
LinuxExport lexport;
Checkbox samba_on, samba_off;
Checkbox writable_on, writable_off;
Checkbox available_on, available_off;
Checkbox guest_on, guest_off, guest_only;
TextField comment;
TextField desc;
Checkbox nfs_on, nfs_off;
TextField rwhosts, rohosts, roothosts;
Checkbox rw[] = new Checkbox[3], ro[] = new Checkbox[3],
root[] = new Checkbox[3];
TextField host[];
Choice lro[], squash[];
SharingWindow(RemoteFile f, FileManager p)
{
file = f; filemgr = p;
setTitle(filemgr.text("share_title", file.path));
sshare = (SambaShare)filemgr.stab.get(file.path);
Object nshare = filemgr.ntab.get(file.path);
if (filemgr.nfsmode == 1)
lexport = (LinuxExport)nshare;
else if (filemgr.nfsmode == 2)
dexport = (DFSAdminExport)nshare;
// setup UI
setLayout(new BorderLayout());
Panel samba = new Panel(), sl = new Panel(), sr = new Panel();
samba.setLayout(new BorderLayout());
Panel st = new Panel();
st.setLayout(new GridLayout(2, 1));
CheckboxGroup sg = new CheckboxGroup();
st.add(samba_off = new Checkbox(filemgr.text("share_soff"), sg,
sshare == null));
st.add(samba_on = new Checkbox(filemgr.text("share_son"), sg,
sshare != null));
samba.add("North", st);
Panel stop = new LinedPanel(filemgr.text("share_sheader"));
setup_leftright(stop, sl, sr);
comment = new TextField(sshare == null ? "" : sshare.comment, 25);
comment.setFont(filemgr.fixed);
add_item(filemgr.text("share_comment"), comment, sl, sr);
Panel ap = new Panel();
ap.setLayout(new GridLayout(1, 0));
CheckboxGroup ag = new CheckboxGroup();
ap.add(available_on = new Checkbox(filemgr.text("yes"), ag,
sshare == null || sshare.available));
ap.add(available_off = new Checkbox(filemgr.text("no"), ag,
sshare != null && !sshare.available));
add_item(filemgr.text("share_available"), ap, sl, sr);
Panel wp = new Panel();
wp.setLayout(new GridLayout(1, 0));
CheckboxGroup wg = new CheckboxGroup();
wp.add(writable_on = new Checkbox(filemgr.text("yes"), wg,
sshare == null || sshare.writable));
wp.add(writable_off = new Checkbox(filemgr.text("no"), wg,
sshare != null && !sshare.writable));
add_item(filemgr.text("share_writable"), wp, sl, sr);
Panel gp = new Panel();
gp.setLayout(new GridLayout(1, 0));
CheckboxGroup gg = new CheckboxGroup();
gp.add(guest_only = new Checkbox(filemgr.text("share_only"), gg,
sshare != null && sshare.guest == 2));
gp.add(guest_on = new Checkbox(filemgr.text("yes"), gg,
sshare == null || sshare.guest == 1));
gp.add(guest_off = new Checkbox(filemgr.text("no"), gg,
sshare != null && sshare.guest == 0));
add_item(filemgr.text("share_guest"), gp, sl, sr);
samba.add("Center", stop);
// Setup NFS UI
Panel nfs = new Panel(), nl = new Panel(), nr = new Panel();
nfs.setLayout(new BorderLayout());
Panel nt = new Panel();
nt.setLayout(new GridLayout(2, 1));
CheckboxGroup ng = new CheckboxGroup();
nt.add(nfs_off = new Checkbox(filemgr.text("share_noff"), ng,
nshare == null));
nt.add(nfs_on = new Checkbox(filemgr.text("share_non"), ng,
nshare != null));
nfs.add("North", nt);
Panel ntop = new LinedPanel(filemgr.text("share_nheader"));
setup_leftright(ntop, nl, nr);
if (filemgr.nfsmode == 1) {
// Linux export mode
nl.setLayout(new GridLayout(0, 1, 2, 2));
nr.setLayout(new GridLayout(0, 1, 2, 2));
nl.add(new Label(filemgr.text("share_host")));
nr.add(new Label(filemgr.text("share_opts")));
int c = lexport==null ? 0 : lexport.host.length;
host = new TextField[c+1];
lro = new Choice[c+1];
squash = new Choice[c+1];
for(int i=0; i<c; i++) {
host[i] = new TextField(lexport.host[i], 20);
host[i].setFont(filemgr.fixed);
lro[i] = robox(lexport.ro[i]);
squash[i] = squashbox(lexport.squash[i]);
nl.add(host[i]);
nr.add(opts_panel(lro[i], squash[i]));
}
host[c] = new TextField("", 20);
host[c].setFont(filemgr.fixed);
lro[c] = robox(false);
squash[c] = squashbox(1);
nl.add(host[c]);
nr.add(opts_panel(lro[c], squash[c]));
}
else if (filemgr.nfsmode == 2) {
// Solaris share mode
desc = new TextField(dexport == null ? "" : dexport.desc, 25);
desc.setFont(filemgr.fixed);
add_item(filemgr.text("share_desc"), desc, nl, nr);
rohosts = add_hosts(filemgr.text("share_ro"),
dexport == null ? "-" : dexport.ro,
ro, nl, nr);
rwhosts = add_hosts(filemgr.text("share_rw"),
dexport == null ? "-" : dexport.rw,
rw, nl, nr);
roothosts = add_hosts(filemgr.text("share_root"),
dexport == null ? "-" : dexport.root,
root, nl, nr);
root[1].getParent().remove(root[1]);
}
else if (filemgr.nfsmode == 3) {
}
nfs.add("Center", ntop);
// Add the appropriate tabs
if (filemgr.sambamode && filemgr.nfsmode != 0) {
TabbedPanel tab = new TabbedPanel();
tab.addItem(filemgr.text("share_samba"), samba);
tab.addItem(filemgr.text("share_nfs"), nfs);
add("Center", tab);
}
else if (filemgr.sambamode)
add("Center", samba);
else if (filemgr.nfsmode != 0)
add("Center", nfs);
// Create save and cancel buttons
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);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == save_b) {
// Update samba settings on server
if (sshare != null && samba_on.getState()) {
// Updating share
sshare.available = available_on.getState();
sshare.writable = writable_on.getState();
sshare.guest = guest_only.getState() ? 2 :
guest_on.getState() ? 1 : 0;
sshare.comment = comment.getText();
String rv[] = filemgr.get_text(
"save_share.cgi?"+sshare.params());
}
else if (sshare != null) {
// Deleting share
String rv[] = filemgr.get_text(
"save_share.cgi?delete=1&"+sshare.params());
filemgr.stab.remove(sshare.path);
}
else if (samba_on.getState()) {
// Creating share
sshare = new SambaShare(file.path,
available_on.getState(),
writable_on.getState(),
guest_only.getState() ? 2 :
guest_on.getState() ? 1 : 0,
comment.getText());
filemgr.stab.put(sshare.path, sshare);
String rv[] = filemgr.get_text(
"save_share.cgi?new=1&"+sshare.params());
}
// Update NFS settings on server
if (filemgr.nfsmode == 1) {
if (lexport != null && nfs_on.getState()) {
// Updating export
export_options(lexport);
String rv[] = filemgr.get_text(
"save_export.cgi?"+lexport.params());
}
else if (lexport != null) {
// Deleting export
String rv[] = filemgr.get_text(
"save_export.cgi?delete=1&"+lexport.params());
filemgr.ntab.remove(lexport.path);
}
else if (nfs_on.getState()) {
// Creating export
lexport = new LinuxExport(file.path, null,
null, null);
export_options(lexport);
String rv[] = filemgr.get_text(
"save_export.cgi?new=1&"+lexport.params());
filemgr.ntab.put(lexport.path, lexport);
}
}
else if (filemgr.nfsmode == 2) {
if (dexport != null && nfs_on.getState()) {
// Updating share
dexport.desc = desc.getText();
dexport.ro = ro[0].getState() ? "-" :
ro[1].getState() ? "" :
rohosts.getText();
dexport.rw = rw[0].getState() ? "-" :
rw[1].getState() ? "" :
rwhosts.getText();
dexport.root = root[0].getState() ? "-" :
roothosts.getText();
String rv[] = filemgr.get_text(
"save_export.cgi?"+dexport.params());
}
else if (dexport != null) {
// Deleting share
String rv[] = filemgr.get_text(
"save_export.cgi?delete=1&"+dexport.params());
filemgr.ntab.remove(dexport.path);
}
else if (nfs_on.getState()) {
// Creating new share
dexport = new DFSAdminExport(file.path,
desc.getText(),
ro[0].getState() ? "-" :
ro[1].getState() ? "" :
rohosts.getText(),
rw[0].getState() ? "-" :
rw[1].getState() ? "" :
rwhosts.getText(),
root[0].getState() ? "-" :
roothosts.getText());
String rv[] = filemgr.get_text(
"save_export.cgi?new=1&"+dexport.params());
filemgr.ntab.put(dexport.path, dexport);
}
}
else if (filemgr.nfsmode == 3) {
}
filemgr.show_files(filemgr.showing_files);
dispose();
}
else if (b == cancel_b)
dispose();
}
void setup_leftright(Panel m, Panel l, Panel r)
{
m.setLayout(new BorderLayout());
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West", l);
p.add("Center", r);
l.setLayout(new GridLayout(0, 1));
r.setLayout(new GridLayout(0, 1));
m.add("North", p);
}
void add_item(String t, Component c, Panel l, Panel r)
{
l.add(new Label(t));
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West", c);
r.add(p);
}
TextField add_hosts(String name, String v, Checkbox cb[],
Panel l, Panel r)
{
Panel p = new Panel();
p.setLayout(new GridLayout(1, 3));
CheckboxGroup g = new CheckboxGroup();
p.add(cb[0] = new Checkbox(filemgr.text("share_none"), g,
v.equals("-")));
p.add(cb[1] = new Checkbox(filemgr.text("share_all"), g,
v.length() == 0));
p.add(cb[2] = new Checkbox(filemgr.text("share_listed"), g,
v.length() > 1));
add_item(name, p, l, r);
TextField t = new TextField(v.equals("-") ? "" : v, 25);
t.setFont(filemgr.fixed);
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<host.length; i++)
if (host[i].getText().length() > 0)
c++;
e.host = new String[c];
e.ro = new boolean[c];
e.squash = new int[c];
for(int i=0,j=0; i<host.length; i++) {
if (host[i].getText().trim().length() > 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, down_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" };
TextField cont;
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);
list.setFont(filemgr.fixed);
tab.addItem(filemgr.text("search_list"), list);
add_item(filemgr.text("search_dir"), dir = new TextField(d, 30), l, r);
dir.setFont(filemgr.fixed);
// Filename
add_item(filemgr.text("search_match"), match = new TextField(20), l, r);
match.setFont(filemgr.fixed);
if (filemgr.search_contents) {
// File contents
add_item(filemgr.text("search_cont"),
cont = new TextField(30), l, r);
cont.setFont(filemgr.fixed);
}
// User or group owners
if (filemgr.can_users) {
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));
user.setFont(filemgr.fixed);
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));
group.setFont(filemgr.fixed);
add_item(filemgr.text("search_group"), gp, l, r);
}
// File type
if (!filemgr.follow_links) {
type = new Choice();
for(int i=0; i<types.length; i++)
type.addItem(filemgr.text("search_types_"+types[i]));
add_item(filemgr.text("search_type"), type, l, r);
}
// File size
CheckboxGroup sg = new CheckboxGroup();
add_item(filemgr.text("search_size"),
sany = new Checkbox(filemgr.text("search_any"), sg, true),
l, r);
Panel mp = new Panel();
mp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
mp.add(smore = new Checkbox(filemgr.text("search_more"), sg, false));
mp.add(more = new TextField(10));
more.setFont(filemgr.fixed);
add_item("", mp, l, r);
Panel lp = new Panel();
lp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
lp.add(sless = new Checkbox(filemgr.text("search_less"), sg, false));
lp.add(less = new TextField(10));
less.setFont(filemgr.fixed);
add_item("", lp, l, r);
if (filemgr.got_filesystems) {
// Search past mounts
CheckboxGroup xg = new CheckboxGroup();
Panel xp = new Panel();
xp.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
xp.add(xoff = new Checkbox(filemgr.text("yes"), xg, true));
xp.add(xon = new Checkbox(filemgr.text("no"), xg, false));
add_item(filemgr.text("search_xdev"), xp, l, r);
}
search.add("West", l); search.add("East", r);
add("Center", tab);
// Create search and cancel buttons
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(down_b = new CbButton(filemgr.get_image("down.gif"),
filemgr.text("search_down"),
CbButton.LEFT, this));
bot.add(search_b = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("search_ok"),
CbButton.LEFT, this));
bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
void add_item(String t, Component c, Panel l, Panel r)
{
l.add(new Label(t));
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West", c);
r.add(p);
}
public void click(CbButton b)
{
if (b == cancel_b)
dispose();
else if (b == search_b) {
// validate inputs and build search URL
String url = "search.cgi";
String d = dir.getText().trim();
if (d.length() == 0 || d.charAt(0) != '/') {
new ErrorWindow(filemgr.text("search_edir"));
return;
}
url += "?dir="+filemgr.urlize(d);
String mt = match.getText().trim();
if (mt.length() == 0) {
mt = "*";
//new ErrorWindow(filemgr.text("search_ematch"));
//return;
}
url += "&match="+filemgr.urlize(mt);
if (type != null && type.getSelectedIndex() > 0)
url += "&type="+types[type.getSelectedIndex()];
if (usel != null && 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 != null && 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 != null && xon.getState())
url += "&xdev=1";
if (cont != null && cont.getText().trim().length() > 0)
url += "&cont="+filemgr.urlize(cont.getText());
// 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<f.length; i++) {
RemoteFile r = new RemoteFile(filemgr, f[i], null);
results[i-1] = r;
Object row[] = rows[i-1] = new Object[3];
row[0] = filemgr.get_image(RemoteFile.tmap[r.type]);
row[1] = r.path;
if (r.size < 1000)
row[2] = filemgr.spad(r.size, 5)+" B";
else if (r.size < 1000000)
row[2] = filemgr.spad(r.size/1000, 5)+" kB";
else
row[2] = filemgr.spad(r.size/1000000, 5)+" MB";
}
list.clear();
list.addItems(rows);
tab.select(filemgr.text("search_list"));
setCursor(DEFAULT_CURSOR);
}
else if (b == down_b) {
// Download selected file (if any)
int num = list.selected();
if (num < 0 || results.length == 0) {
new ErrorWindow(filemgr.text("search_edown"));
return;
}
filemgr.download_file(results[num]);
}
}
public void singleClick(MultiColumn list, int num)
{
}
// go to the directory of the double-clicked file
public void doubleClick(MultiColumn list, int num)
{
RemoteFile f = results[num];
int sl = f.path.lastIndexOf('/');
String dir = sl == 0 ? "/" : f.path.substring(0, sl);
filemgr.find_directory(dir, true);
RemoteFile l[] = filemgr.showing_list;
for(int i=0; i<l.length; i++) {
if (l[i].name.equals(f.name)) {
// select the file in the list
filemgr.files.select(i+1);
filemgr.files.scrollto(i+1);
break;
}
}
dispose();
}
public void headingClicked(MultiColumn list, int col)
{
}
}
// A popup window showing previously entered paths
class HistoryWindow extends FixedFrame
implements CbButtonCallback,ActionListener
{
java.awt.List hlist;
CbButton ok_b, cancel_b;
FileManager filemgr;
HistoryWindow(FileManager p)
{
filemgr = p;
setTitle(filemgr.text("history_title"));
// Setup UI
hlist = new java.awt.List();
for(int i=0; i<filemgr.history_list.size(); i++) {
hlist.add((String)filemgr.history_list.elementAt(i));
}
hlist.addActionListener(this);
setLayout(new BorderLayout());
add("Center", hlist);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(ok_b = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("history_ok"),
CbButton.LEFT, this));
bot.add(cancel_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == cancel_b)
dispose();
else if (b == ok_b) {
// Go to the selected directory
String p = hlist.getSelectedItem();
if (p != null) {
filemgr.find_directory(p, true);
dispose();
}
}
}
public void actionPerformed(ActionEvent e)
{
// List entry double-clicked .. go to it
String p = hlist.getSelectedItem();
filemgr.find_directory(p, true);
dispose();
}
public Dimension minimumSize()
{
return new Dimension(300, 300);
}
}
class FileSystem
{
String mount;
String dev;
String type;
String opts[];
boolean acls;
boolean attrs;
boolean ext;
boolean mtab, fstab;
FileSystem(String l)
{
StringSplitter tok = new StringSplitter(l, ' ');
mount = tok.nextToken();
dev = tok.nextToken();
type = tok.nextToken();
String optstr = tok.nextToken();
acls = tok.nextToken().equals("1");
attrs = tok.nextToken().equals("1");
ext = tok.nextToken().equals("1");
mtab = tok.nextToken().equals("1");
fstab = tok.nextToken().equals("1");
StringTokenizer tok2 = new StringTokenizer(optstr, ",");
opts = new String[tok2.countTokens()];
for(int i=0; i<opts.length; i++)
opts[i] = tok2.nextToken();
}
}
class ACLEntry
{
FileManager filemgr;
RemoteFile file;
boolean def;
String type;
String owner;
boolean read, write, exec;
boolean empty_owner = false;
ACLEntry(String l, ACLWindow w)
{
filemgr = w.filemgr;
file = w.file;
StringSplitter tok = new StringSplitter(l, ':');
type = tok.nextToken();
if (type.equals("default")) {
def = true;
type = tok.nextToken();
}
if (!type.equals("mask") && !type.equals("other")) {
owner = tok.nextToken();
if (owner.length() == 0)
owner = null;
}
String rwx = tok.nextToken();
if (rwx.length() == 0) {
rwx = tok.nextToken(); // getfacl outputs a blank owner for
// mask and other on some systems
empty_owner = true;
}
read = (rwx.charAt(0) == 'r');
write = (rwx.charAt(1) == 'w');
exec = (rwx.charAt(2) == 'x');
}
ACLEntry(ACLWindow w)
{
filemgr = w.filemgr;
file = w.file;
}
String[] getRow()
{
String rv[] = new String[3];
String t = def ? "acltype_default_"+type : "acltype_"+type;
rv[0] = filemgr.text(t);
if (type.equals("mask") || type.equals("other") ||
(def && owner == null))
rv[1] = "";
else if (owner != null)
rv[1] = owner;
else if (type.equals("user"))
rv[1] = filemgr.text("eacl_user", file.user);
else
rv[1] = filemgr.text("eacl_group", file.group);
rv[2] = "";
if (read) rv[2] += filemgr.text("info_read")+" ";
if (write) rv[2] += filemgr.text("info_write")+" ";
if (exec) rv[2] += filemgr.text("info_exec")+" ";
return rv;
}
public String toString()
{
String rv = def ? "default:" : "";
rv += type+":";
if (!type.equals("mask") && !type.equals("other") || empty_owner)
// mask and other types have no owner field at all, except
// on some operating systems like FreeBSD where it is empty
rv += (owner == null ? "" : owner)+":";
rv += (read ? 'r' : '-');
rv += (write ? 'w' : '-');
rv += (exec ? 'x' : '-');
return rv;
}
}
class ACLEditor extends FixedFrame implements CbButtonCallback
{
FileManager filemgr;
ACLWindow aclwin;
ACLEntry acl;
boolean creating;
CbButton ok, del;
Checkbox read, write, exec, owner1, owner2;
TextField owner;
// Editing an existing ACL entry
ACLEditor(ACLWindow w, ACLEntry a)
{
aclwin = w;
filemgr = aclwin.filemgr;
acl = a;
creating = false;
makeUI();
}
// Creating a new ACL entry
ACLEditor(ACLWindow w, String type, boolean def, boolean empty_owner)
{
aclwin = w;
filemgr = aclwin.filemgr;
acl = new ACLEntry(aclwin);
acl.def = def;
acl.type = type;
acl.empty_owner = empty_owner;
creating = true;
makeUI();
}
void makeUI()
{
setTitle(filemgr.text(creating ? "eacl_create" : "eacl_edit"));
setLayout(new BorderLayout());
Panel left = new Panel();
left.setLayout(new GridLayout(0, 1));
add("West", left);
Panel right = new Panel();
right.setLayout(new GridLayout(0, 1));
add("East", right);
left.add(new Label(filemgr.text("eacl_acltype")));
TextField type;
right.add(type = new TextField(
(acl.def ? "default " : "")+acl.type, 20));
type.setEditable(false);
type.setFont(filemgr.fixed);
if (!acl.type.equals("mask") && !acl.type.equals("other")) {
left.add(new Label(filemgr.text("eacl_aclname")));
if (acl.def) {
// A default user or group ACL .. can be for
// a specific user, or for the file owner
Panel op = new Panel();
op.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
CheckboxGroup gr = new CheckboxGroup();
op.add(owner1 = new Checkbox(filemgr.text("eacl_owner"),
gr, acl.owner == null));
op.add(owner2 = new Checkbox("",
gr, acl.owner != null));
op.add(owner = new TextField(
acl.owner == null ? "" : acl.owner, 20));
owner.setFont(filemgr.fixed);
right.add(op);
}
else if (creating || acl.owner != null) {
// A user or group ACL for a specific user
owner = new TextField(
acl.owner == null ? "" : acl.owner, 20);
owner.setFont(filemgr.fixed);
right.add(owner);
}
else {
// A user or group ACL for the file owner
String str;
if (acl.type.equals("user"))
str = filemgr.text("eacl_user", aclwin.file.user);
else
str = filemgr.text("eacl_group", aclwin.file.group);
TextField o = new TextField(str);
o.setEditable(false);
o.setFont(filemgr.fixed);
right.add(o);
}
}
left.add(new Label(filemgr.text("eacl_aclperms")));
Panel pp = new Panel();
pp.setLayout(new FlowLayout(FlowLayout.RIGHT));
pp.add(read = new Checkbox(filemgr.text("info_read"), null, acl.read));
pp.add(write = new Checkbox(filemgr.text("info_write"), null, acl.write));
pp.add(exec = new Checkbox(filemgr.text("info_exec"), null, acl.exec));
right.add(pp);
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 && (acl.owner != null || acl.def))
bot.add(del = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("delete"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == ok) {
// Update or add the ACL entry
if (owner1 != null && owner1.getState()) {
acl.owner = null;
}
else if (owner != null) {
String o = owner.getText().trim();
if (o.length() == 0 && !acl.def) {
new ErrorWindow(filemgr.text("eacl_eowner"));
return;
}
acl.owner = owner.getText();
if (acl.owner.length() == 0)
acl.owner = null;
}
acl.read = read.getState();
acl.write = write.getState();
acl.exec = exec.getState();
if (creating) {
// Add to the ACL table
aclwin.acllist.addElement(acl);
aclwin.acltable.addItem(acl.getRow());
}
else {
// Update the table
int idx = aclwin.acllist.indexOf(acl);
aclwin.acltable.modifyItem(acl.getRow(), idx);
}
dispose();
}
else if (b == del) {
// Remove this entry
int idx = aclwin.acllist.indexOf(acl);
aclwin.acllist.removeElementAt(idx);
aclwin.acltable.deleteItem(idx);
dispose();
}
}
public void dispose()
{
aclwin.edmap.remove(acl);
super.dispose();
}
}
class ACLWindow extends FixedFrame implements CbButtonCallback,MultiColumnCallback
{
FileManager filemgr;
RemoteFile file;
Vector acllist = new Vector();
Hashtable edmap = new Hashtable();
CbButton ok, cancel, add;
Choice addtype;
MultiColumn acltable;
String acltypes[] = { "user", "group", "mask",
"default user", "default group", "default other",
"default mask" };
ACLWindow(FileManager p, RemoteFile f)
{
super(400, 300);
setTitle(p.text("eacl_title", f.path));
filemgr = p;
file = f;
// Get the ACLs
String a[] = filemgr.get_text(
"getfacl.cgi?file="+filemgr.urlize(file.path));
if (a[0].length() != 0) {
new ErrorWindow(filemgr.text("eacl_eacls", a[0]));
return;
}
// Create the UI
setLayout(new BorderLayout());
String titles[] = { filemgr.text("eacl_acltype"),
filemgr.text("eacl_aclname"),
filemgr.text("eacl_aclperms") };
acltable = new MultiColumn(titles, this);
for(int i=1; i<a.length; i++) {
ACLEntry acl = new ACLEntry(a[i], this);
acllist.addElement(acl);
acltable.addItem(acl.getRow());
}
add("Center", acltable);
Panel abot = new Panel();
abot.setLayout(new FlowLayout(FlowLayout.RIGHT));
abot.add(add = new CbButton(filemgr.get_image("add.gif"),
filemgr.text("eacl_add"),
CbButton.LEFT, this));
int len = file.type == RemoteFile.DIR ? acltypes.length : 3;
abot.add(addtype = new Choice());
for(int i=0; i<len; i++) {
String t = "acltype_"+acltypes[i].replace(' ', '_');
addtype.addItem(filemgr.text(t));
}
abot.add(new Label(" "));
abot.add(ok = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("save"),
CbButton.LEFT, this));
abot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", abot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == ok) {
// Check if there are any defaults, and if so there must
// be default user, group and other
boolean anydef = false, defuser = false,
defgroup = false, defother = false;
for(int i=0; i<acllist.size(); i++) {
ACLEntry e = (ACLEntry)acllist.elementAt(i);
if (e.def) anydef = true;
if (e.def && e.owner == null) {
if (e.type.equals("user")) defuser = true;
if (e.type.equals("group")) defgroup = true;
if (e.type.equals("other")) defother = true;
}
}
if (anydef && (!defuser || !defgroup || !defother)) {
new ErrorWindow(filemgr.text("eacl_edefaults"));
return;
}
// Save the ACLs
String aclstr = "";
for(int i=0; i<acllist.size(); i++)
aclstr += (ACLEntry)acllist.elementAt(i)+"\n";
String rv[] = filemgr.get_text("setfacl.cgi?file="+
filemgr.urlize(file.path)+
"&acl="+filemgr.urlize(aclstr));
if (rv[0].length() > 0)
new ErrorWindow(filemgr.text("eacl_efailed",
file.path, rv[0]));
else
dispose();
}
else if (b == add) {
// Open a window for a new ACL entry
String t = acltypes[addtype.getSelectedIndex()];
String d = "default ";
boolean def = t.startsWith(d);
if (def)
t = t.substring(d.length());
if (t.equals("mask")) {
// Only allow one mask
for(int i=0; i<acllist.size(); i++) {
ACLEntry a = (ACLEntry)acllist.elementAt(i);
if (a.type.equals(t) && a.def == def) {
new ErrorWindow(filemgr.text(def ?
"eacl_edefmask" : "eacl_emask"));
return;
}
}
}
// Check if owner field exists and is empty for existing
// mask or other fields
boolean new_empty_owner = false;
for(int i=0; i<acllist.size(); i++) {
ACLEntry a = (ACLEntry)acllist.elementAt(i);
if ((a.type.equals("mask") || a.type.equals("other")) &&
a.empty_owner) {
new_empty_owner = true;
}
}
new ACLEditor(this, t, def, new_empty_owner);
}
else if (b == cancel) {
// Don't save
dispose();
}
}
// Bring up an editor for an ACL
public void doubleClick(MultiColumn list, int num)
{
int idx = list.selected();
if (idx >= 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<a.length; i++) {
FileAttribute at = new FileAttribute(a[i], filemgr);
attrlist.addElement(at);
attrtable.addItem(at.getRow());
}
add("Center", attrtable);
Panel abot = new Panel();
abot.setLayout(new FlowLayout(FlowLayout.RIGHT));
abot.add(add = new CbButton(filemgr.get_image("add.gif"),
filemgr.text("attr_add"),
CbButton.LEFT, this));
abot.add(new Label(" "));
abot.add(ok = new CbButton(filemgr.get_image("save.gif"),
filemgr.text("save"),
CbButton.LEFT, this));
abot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", abot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == ok) {
// Save the attributes
String pstr = "";
for(int i=0; i<attrlist.size(); i++) {
FileAttribute at = (FileAttribute)attrlist.elementAt(i);
pstr += "&name"+i+"="+filemgr.urlize(at.name)+
"&value"+i+"="+filemgr.urlize(at.value);
}
String rv[] = filemgr.get_text("setattrs.cgi?file="+
filemgr.urlize(file.path)+pstr);
if (rv[0].length() > 0)
new ErrorWindow(filemgr.text("attr_efailed",
file.path, rv[0]));
else
dispose();
}
else if (b == add) {
// Open a window for a new ACL entry
new AttributeEditor(this);
}
else if (b == cancel) {
// Don't save
dispose();
}
}
// Bring up an editor for an ACL
public void doubleClick(MultiColumn list, int num)
{
int idx = list.selected();
if (idx >= 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));
name.setFont(filemgr.fixed);
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);
Util.recursiveBody(this);
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<a[1].length(); i++)
attrmap.put(a[1].substring(i, i+1), "");
// Create the UI
setLayout(new BorderLayout());
Panel top = new LinedPanel(filemgr.text("ext_header"));
top.setLayout(new GridLayout(0, 1));
cbs = new Checkbox[attrs.length];
for(int i=0; i<attrs.length; i++) {
cbs[i] = new Checkbox(filemgr.text("eattr_"+attrs[i]));
cbs[i].setState(attrmap.get(attrs[i]) != null);
top.add(cbs[i]);
}
add("Center", top);
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));
bot.add(cancel = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("cancel"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == ok) {
// Save the attributes (including unknown ones)
String astr = "";
for(int i=0; i<cbs.length; i++) {
if (cbs[i].getState())
astr += attrs[i];
attrmap.remove(attrs[i]);
}
for(Enumeration e = attrmap.keys(); e.hasMoreElements(); )
astr += e.nextElement();
// Try to set on the server
String rv[] = filemgr.get_text("setext.cgi?file="+
filemgr.urlize(file.path)+"&attrs="+astr);
if (rv[0].length() > 0)
new ErrorWindow(filemgr.text("ext_efailed",
file.path, rv[0]));
else
dispose();
}
else if (b == cancel) {
dispose();
}
}
}
class MountWindow extends FixedFrame implements CbButtonCallback
{
CbButton yes, no;
FileManager filemgr;
FileSystem fs;
RemoteFile file;
MountWindow(FileManager filemgr, FileSystem fs, RemoteFile file)
{
super();
setTitle(filemgr.text(fs.mtab ? "mount_title2" : "mount_title1"));
this.filemgr = filemgr;
this.fs = fs;
this.file = file;
// Create the UI
setLayout(new BorderLayout());
Panel cen = new BorderPanel(1, Util.body);
cen.setLayout(new GridLayout(1, 1));
String rusure = fs.mtab ? "mount_rusure2" : "mount_rusure1";
cen.add(new Label(filemgr.text(rusure, fs.mount, fs.dev)));
add("Center", cen);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.CENTER));
bot.add(yes = new CbButton(filemgr.text("yes"), this));
bot.add(no = new CbButton(filemgr.text("no"), this));
add("South", bot);
pack();
show();
Util.recursiveBody(this);
}
public void click(CbButton b)
{
if (b == yes) {
// Go ahread and do it!
String rv[] = filemgr.get_text("mount.cgi?dir="+
filemgr.urlize(fs.mount));
dispose();
if (rv[0].equals("")) {
// It worked - refresh this directory and the mount list
filemgr.get_filesystems();
FileNode d = (FileNode)filemgr.nodemap.get(file);
if (d != null) {
d.setimage();
d.known = false;
d.file.list = null;
d.fill();
}
if (fs.mtab)
filemgr.show_files(file.directory);
else
filemgr.show_files(filemgr.showing_files);
}
else {
// Failed - show the error
new ErrorWindow(filemgr.text(
fs.mtab ? "mount_err2" : "mount_err1",
fs.mount, rv[0]));
}
}
else {
// Just close the window
dispose();
}
}
}
// A label that is limited to a maximum number of characters wide
class MultiLabel extends BorderPanel
{
public MultiLabel(String s, int max)
{
this(s, max, 1);
}
public MultiLabel(String s, int max, int b)
{
this(s, max, b, Label.CENTER);
}
public MultiLabel(String s, int max, int b, int align)
{
super(b, Util.body);
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<v.size(); i++) {
Label l = new Label((String)v.elementAt(i), Label.CENTER);
add(l);
}
}
}
// A window for choosing the format in which a directory will be downloaded
class DownloadDirWindow extends FixedFrame implements CbButtonCallback
{
CbButton zip, tgz, tar, cancel;
FileManager filemgr;
RemoteFile file;
DownloadDirWindow(FileManager filemgr, RemoteFile file)
{
super();
setTitle(filemgr.text("ddir_title"));
this.filemgr = filemgr;
this.file = file;
// Create the UI
setLayout(new BorderLayout());
Panel cen = new BorderPanel(1, Util.body);
cen.setLayout(new GridLayout(1, 1));
cen.add(new Label(filemgr.text("ddir_rusure", file.path)));
add("Center", cen);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.CENTER));
bot.add(zip = new CbButton(filemgr.text("ddir_zip"), this));
bot.add(tgz = new CbButton(filemgr.text("ddir_tgz"), this));
bot.add(tar = new CbButton(filemgr.text("ddir_tar"), this));
bot.add(cancel = new CbButton(filemgr.text("cancel"), this));
add("South", bot);
pack();
show();
Util.recursiveBody(this);
}
public void click(CbButton b)
{
if (b == cancel) {
// just close the window
dispose();
}
else {
// open the download window
int format = b == zip ? 1 :
b == tgz ? 2 : 3;
dispose();
filemgr.open_file_window(file, true, format);
}
}
}
class PreviewWindow extends Frame implements CbButtonCallback
{
CbButton close_b;
RemoteFile file;
FileManager filemgr;
ImagePanel ip;
// Previewing a file
public PreviewWindow(FileManager p, RemoteFile f)
{
//super(350, 350);
file = f; filemgr = p;
makeUI();
setTitle(filemgr.text("preview_title", file.path));
// Load the file
try {
URL u = new URL(filemgr.getDocumentBase(),
"preview.cgi"+filemgr.urlize(file.path)+
"?rand="+System.currentTimeMillis()+
"&trust="+filemgr.trust+
filemgr.extra);
URLConnection uc = u.openConnection();
filemgr.set_cookie(uc);
int len = uc.getContentLength();
InputStream is = uc.getInputStream();
byte buf[];
if (len >= 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;
}
}
// Check if this is really an error
if (uc.getContentType().equals("text/plain")) {
String s = new String(buf, 0);
new ErrorWindow(s);
dispose();
return;
}
// Show the image
Image img = Toolkit.getDefaultToolkit().createImage(buf);
MediaTracker waiter = new MediaTracker(this);
waiter.addImage(img, 666);
try { waiter.waitForAll(); }
catch(InterruptedException e) { }
if (img.getWidth(this) <= 0) {
new ErrorWindow(filemgr.text("preview_bad"));
dispose();
return;
}
ip.setImage(img);
pack();
show();
}
catch(Exception e) { e.printStackTrace(); }
}
void makeUI()
{
setLayout(new BorderLayout());
// Image viewing area
BorderPanel mid = new BorderPanel(2, Util.body);
mid.setLayout(new BorderLayout());
ip = new ImagePanel(null);
mid.add("Center", ip);
add("Center", mid);
// Button panel
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(close_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("close"),
CbButton.LEFT, this));
add("South", bot);
Util.recursiveBody(this);
}
public void click(CbButton b)
{
if (b == close_b) {
// Just close
dispose();
}
}
}
class ImagePanel extends Panel
{
Image img;
public ImagePanel(Image img)
{
this.img = img;
}
public void paint(Graphics g)
{
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
public void setImage(Image img)
{
this.img = img;
repaint();
}
public Dimension minimumSize()
{
return new Dimension(img.getWidth(this), img.getHeight(this));
}
public Dimension preferredSize()
{
return minimumSize();
}
}
class ExtractWindow extends FixedFrame implements CbButtonCallback
{
CbButton yes, yesdelete, no, show;
FileManager filemgr;
RemoteFile file;
ExtractWindow(FileManager filemgr, RemoteFile file)
{
super();
setTitle(filemgr.text("extract_title"));
this.filemgr = filemgr;
this.file = file;
// Create the UI
setLayout(new BorderLayout());
Panel cen = new BorderPanel(1, Util.body);
cen.setLayout(new GridLayout(3, 1));
cen.add(new Label(filemgr.text("extract_rusure")));
cen.add(new Label(file.path));
cen.add(new Label(filemgr.text("extract_rusure2")));
add("Center", cen);
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.CENTER));
bot.add(yes = new CbButton(filemgr.text("yes"), this));
bot.add(yesdelete = new CbButton(filemgr.text("extract_yes"), this));
bot.add(no = new CbButton(filemgr.text("no"), this));
bot.add(show = new CbButton(filemgr.text("extract_show"), this));
add("South", bot);
pack();
show();
Util.recursiveBody(this);
}
public void click(CbButton b)
{
if (b == yes || b == yesdelete) {
// Go ahread and do it!
String rv[] = filemgr.get_text("extract.cgi?file="+
filemgr.urlize(file.path)+
"&delete="+(b == yesdelete ? 1 : 0));
dispose();
if (rv[0].equals("")) {
// It worked - refresh the directory
RemoteFile par = file.directory;
FileNode d = (FileNode)filemgr.nodemap.get(par);
if (d != null) {
d.setimage();
d.known = false;
d.file.list = null;
d.fill();
}
filemgr.show_files(filemgr.showing_files);
}
else {
// Failed - show the error
new ErrorWindow(filemgr.text("extract_err", rv[0]));
}
}
else if (b == show) {
// Open window just showing contents
String rv[] = filemgr.get_text("contents.cgi?file="+
filemgr.urlize(file.path));
dispose();
if (rv[0].equals("")) {
// Worked - show the files
new ContentsWindow(file, filemgr, rv);
}
else {
// Failed - show the error
new ErrorWindow(filemgr.text("extract_err2", rv[0]));
}
}
else {
// Just close the window
dispose();
}
}
}
class ContentsWindow extends FixedFrame implements CbButtonCallback
{
RemoteFile file;
FileManager filemgr;
CbButton close_b;
ContentsWindow(RemoteFile f, FileManager p, String rv[])
{
file = f;
filemgr = p;
// Create UI
setTitle(f.path);
setLayout(new BorderLayout());
Panel bot = new Panel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(close_b = new CbButton(filemgr.get_image("cancel.gif"),
filemgr.text("close"),
CbButton.LEFT, this));
add("South", bot);
// Create text area showing contents
String lines = "";
for(int i=1; i<rv.length; i++) {
lines = lines + rv[i] + "\n";
}
TextArea contents = new TextArea(lines, 30, 60);
contents.setEditable(false);
add("Center", contents);
add("North", new Label(filemgr.text("extract_shown")));
Util.recursiveBody(this);
pack();
show();
}
public void click(CbButton b)
{
if (b == close_b) {
// Just close
dispose();
}
}
}