Test checkin of some modules

This commit is contained in:
Jamie Cameron
2007-04-12 19:28:29 +00:00
commit 27d3d6cb97
358 changed files with 47126 additions and 0 deletions

67
file/BorderPanel.java Executable file
View File

@ -0,0 +1,67 @@
import java.awt.*;
class BorderPanel extends Panel
{
int border = 5; // size of border
Color col1 = Util.light_edge;
Color col2 = Util.dark_edge;
Color body;
BorderPanel()
{
}
BorderPanel(int w)
{
border = w;
}
BorderPanel(int w, Color cb)
{
border = w;
body = cb;
}
BorderPanel(int w, Color c1, Color c2)
{
border = w;
col1 = c1; col2 = c2;
}
BorderPanel(int w, Color c1, Color c2, Color cb)
{
border = w;
col1 = c1; col2 = c2; body = cb;
}
BorderPanel(Color c1, Color c2)
{
col1 = c1; col2 = c2;
}
public Insets insets()
{
return new Insets(border+2, border+2, border+2, border+2);
}
public void paint(Graphics g)
{
if (body != null) {
g.setColor(body);
g.fillRect(0, 0, size().width, size().height);
}
super.paint(g);
int w = size().width-1, h = size().height-1;
g.setColor(col1);
for(int i=0; i<border; i++) {
g.drawLine(i,i,w-i,i);
g.drawLine(i,i,i,h-i);
}
g.setColor(col2);
for(int i=0; i<border; i++) {
g.drawLine(w-i,h-i, w-i,i);
g.drawLine(w-i,h-i, i,h-i);
}
}
}

33
file/CHANGELOG Normal file
View File

@ -0,0 +1,33 @@
---- Changes since 1.130 ----
An uploaded zip, tar or tar.gz file can be extracted in the directory it was uploaded to.
Directories can now be downloaded as zip, tar or tar.gz files
Added improved access control options to hide buttons.
Added a chroot access control option to hide all directories above it.
---- Changes since 1.190 ----
Added checkbox for saving text files in DOS mode.
Users can now be prevented from accessing certain directories by a new option on the access control page.
---- Changes since 1.240 ----
When searching for files, you can now search by their contents too.
Added a Preview button, for viewing a scaled-down version of a GIF, JPEG or PNG image.
---- Changes since 1.250 ----
Absolute and relative paths like /tmp/foo and bar/foo can be used when renaming a file.
The GD Perl module will be used for scaling preview images, if installed.
---- Changes since 1.260 ----
Added a button for editing HTML files, using a rich-text editor.
---- Changes since 1.270 ----
Added Module Config options for changing the font size for buttons and regular text.
---- Changes since 1.290 ----
Added the ability to extract tar.bz2 files.
Added a History button next to the field for entering a directory to show, for quickly navigating to recently entered paths.
Added text fields to the file info window showing the total size, number of sub-files and number of sub-directories in a directory. These are only populated when a new 'Get Size' button is clicked.
---- Changes since 1.300 ----
Added ACL options to prevent users from editing file permissions or ownership in the Info window, to stop filesystem mount points from being shown, and to restrict file contents searches.
Added Extract button for un-compressing tar, tgz, zip and gz archives on the server.
Added a Download button to the search results window, for downloading a selected matching file.
---- Changes since 1.310 ----
Added a popup progress window to track large uploads.
---- Changes since 1.320 ----
Removed the HTML editing button, and changed the Edit button to detect HTML files and launch the HTML editor instead (optional on the Module Config page).
Added a button for creating a new HTML file.
---- Changes since 1.330 ----
Replaced the HTMLarea widget for editing .html files with Xinha.

264
file/CbButton.java Normal file
View File

@ -0,0 +1,264 @@
import java.awt.*;
import java.util.*;
public class CbButton extends Canvas
{
public static final int LEFT = 0;
public static final int RIGHT = 1;
public static final int ABOVE = 2;
public static final int BELOW = 3;
Image image;
String string;
CbButtonCallback callback;
int imode;
int iwidth, iheight, pwidth, pheight, twidth, theight;
boolean inside, indent;
CbButtonGroup group;
boolean selected;
Color lc1 = Util.light_edge, lc2 = Util.body, lc3 = Util.dark_edge;
Color hc1 = Util.light_edge_hi, hc2 = Util.body_hi, hc3 = Util.dark_edge_hi;
public CbButton(Image i, CbButtonCallback cb)
{
this(i, null, LEFT, cb);
}
public CbButton(String s, CbButtonCallback cb)
{
this(null, s, LEFT, cb);
}
public CbButton(Image i, String s, int im, CbButtonCallback cb)
{
image = i;
string = s;
imode = im;
callback = cb;
if (image != null) {
iwidth = Util.getWidth(image);
iheight = Util.getHeight(image);
}
if (string != null) {
twidth = Util.fnm.stringWidth(string);
theight = Util.fnm.getHeight();
}
if (image != null && string != null) {
switch(imode) {
case LEFT:
case RIGHT:
pwidth = iwidth + twidth + 6;
pheight = Math.max(iheight , theight) + 4;
break;
case ABOVE:
case BELOW:
pwidth = Math.max(iwidth, twidth) + 4;
pheight = iheight + theight + 6;
break;
}
}
else if (image != null) {
pwidth = iwidth + 4;
pheight = iheight + 4;
}
else if (string != null) {
pwidth = twidth + 8;
pheight = theight + 8;
}
}
/**Make this button part of a mutual-exclusion group. Only one such
* button can be indented at a time
*/
public void setGroup(CbButtonGroup g)
{
group = g;
group.add(this);
}
/**Make this button the selected one in it's group
*/
public void select()
{
if (group != null)
group.select(this);
}
/**Display the given string
*/
public void setText(String s)
{
string = s;
image = null;
twidth = Util.fnm.stringWidth(string);
theight = Util.fnm.getHeight();
repaint();
}
/**Display the given image
*/
public void setImage(Image i)
{
string = null;
image = i;
iwidth = Util.getWidth(image);
iheight = Util.getHeight(image);
repaint();
}
/**Display the given image and text, with the given alignment mode
*/
public void setImageText(Image i, String s, int m)
{
image = i;
string = s;
imode = m;
twidth = Util.fnm.stringWidth(string);
theight = Util.fnm.getHeight();
iwidth = Util.getWidth(image);
iheight = Util.getHeight(image);
repaint();
}
public void paint(Graphics g)
{
Color c1 = inside ? hc1 : lc1,
c2 = inside ? hc2 : lc2,
c3 = inside ? hc3 : lc3;
int w = size().width, h = size().height;
Color hi = indent||selected ? c3 : c1,
lo = indent||selected ? c1 : c3;
g.setColor(c2);
g.fillRect(0, 0, w-1, h-1);
g.setColor(hi);
g.drawLine(0, 0, w-2, 0);
g.drawLine(0, 0, 0, h-2);
g.setColor(lo);
g.drawLine(w-1, h-1, w-1, 1);
g.drawLine(w-1, h-1, 1, h-1);
if (inside) {
/* g.setColor(hi);
g.drawLine(1, 1, w-3, 1);
g.drawLine(1, 1, 1, h-3); */
g.setColor(lo);
g.drawLine(w-2, h-2, w-2, 2);
g.drawLine(w-2, h-2, 2, h-2);
}
g.setColor(c3);
g.setFont(Util.f);
if (image != null && string != null) {
if (imode == LEFT) {
Dimension is = imgSize(w-twidth-6, h-4);
g.drawImage(image, (w - is.width - twidth - 2)/2,
(h-is.height)/2, is.width, is.height, this);
g.drawString(string,
(w - is.width - twidth - 2)/2 +is.width +2,
(h + theight - Util.fnm.getDescent())/2);
}
else if (imode == RIGHT) {
}
else if (imode == ABOVE) {
//Dimension is = imgSize(w-4, h-theight-6);
g.drawImage(image, (w - iwidth)/2,
(h - iheight - theight - 2)/2,
iwidth, iheight, this);
g.drawString(string, (w - twidth)/2, iheight+Util.fnm.getHeight()+2);
}
else if (imode == BELOW) {
}
}
else if (image != null) {
Dimension is = imgSize(w-4, h-4);
g.drawImage(image, (w - is.width)/2, (h-is.height)/2,
is.width, is.height, this);
}
else if (string != null) {
g.drawString(string, (w - twidth)/2,
(h+theight-Util.fnm.getDescent())/2);
}
}
public void update(Graphics g) { paint(g); }
public boolean mouseEnter(Event e, int x, int y)
{
inside = true;
repaint();
return true;
}
public boolean mouseExit(Event e, int x, int y)
{
inside = false;
repaint();
return true;
}
public boolean mouseDown(Event e, int x, int y)
{
indent = true;
repaint();
return true;
}
public boolean mouseUp(Event e, int x, int y)
{
if (x >= 0 && y >= 0 && x < size().width && y < size().height) {
if (callback != null)
callback.click(this);
select();
}
indent = false;
repaint();
return true;
}
public Dimension preferredSize()
{
return new Dimension(pwidth, pheight);
}
public Dimension minimumSize()
{
return preferredSize();
}
private Dimension imgSize(int mw, int mh)
{
float ws = (float)mw/(float)iwidth,
hs = (float)mh/(float)iheight;
float s = ws < hs ? ws : hs;
if (s > 1) s = 1;
return new Dimension((int)(iwidth*s), (int)(iheight*s));
}
}
interface CbButtonCallback
{
void click(CbButton b);
}
class CbButtonGroup
{
Vector buttons = new Vector();
void add(CbButton b)
{
buttons.addElement(b);
}
void select(CbButton b)
{
for(int i=0; i<buttons.size(); i++) {
CbButton but = (CbButton)buttons.elementAt(i);
but.selected = (b == but);
but.repaint();
}
}
}

51
file/CbColorButton.java Normal file
View File

@ -0,0 +1,51 @@
import java.awt.*;
import java.util.*;
/**A component for choosing a color
*/
public class CbColorButton extends Panel implements CbButtonCallback,
CbColorWindowCallback
{
Color col;
CbButton but;
Vector pal;
Image swatch = Util.createImage(32, 16);
Graphics g = swatch.getGraphics();
CbColorWindow win;
CbColorButton(Color c)
{
this(c, new Vector());
}
CbColorButton(Color c, Vector p)
{
if (c == null) c = Color.black;
col = c;
g.setColor(col); g.fillRect(0, 0, 32, 16);
setLayout(new BorderLayout());
add("Center", but = new CbButton(swatch, this));
}
public void click(CbButton b)
{
if (win == null)
win = new CbColorWindow(col, this);
}
public void chosen(CbColorWindow w, Color c)
{
if (c != null) {
col = c;
g.setColor(col); g.fillRect(0, 0, 32, 16);
but.repaint();
}
win = null;
}
public Vector palette(CbColorWindow w)
{
return pal;
}
}

226
file/CbColorWindow.java Normal file
View File

@ -0,0 +1,226 @@
import java.awt.*;
import java.util.*;
/**A window for choosing a colour, either from a pre-set palette
* or from a color cube
*/
class CbColorWindow extends FixedFrame implements CbButtonCallback
{
CbColorWindowCallback callback;
Color col;
Vector pal;
static Vector defpal = new Vector();
Image palimg[] = new Image[12];
CbButton palbut[] = new CbButton[12];
int curpal = -1;
CbButton ok, cancel;
CbColorWindowCube ccube;
static
{
defpal.addElement(Color.black);
defpal.addElement(Color.blue);
defpal.addElement(Color.cyan);
defpal.addElement(Color.gray);
defpal.addElement(Color.green);
defpal.addElement(Color.darkGray);
defpal.addElement(Color.magenta);
defpal.addElement(Color.orange);
defpal.addElement(Color.pink);
defpal.addElement(Color.red);
defpal.addElement(Color.white);
defpal.addElement(Color.yellow);
}
CbColorWindow(Color c, CbColorWindowCallback cb)
{
col = c;
callback = cb;
// Setup color vector
pal = callback.palette(this);
if (pal == null)
pal = defpal;
else if (pal.size() == 0)
for(int i=0; i<12; i++)
pal.addElement(defpal.elementAt(i));
// Create palette images
for(int i=0; i<12; i++) {
palimg[i] = Util.createImage(16, 16);
updatePal(i);
}
// create UI
setLayout(new BorderLayout());
Panel bot = new GrayPanel();
bot.setLayout(new FlowLayout(FlowLayout.RIGHT));
bot.add(ok = new CbButton("Ok", this));
bot.add(cancel = new CbButton("Cancel", this));
add("South", bot);
Panel mid = new BorderPanel(1);
mid.setLayout(new BorderLayout());
Panel midbot = new GrayPanel();
midbot.setLayout(new GridLayout(2, 6, 4, 4));
CbButtonGroup g = new CbButtonGroup();
for(int i=0; i<12; i++) {
midbot.add(palbut[i] = new CbButton(palimg[i], this));
palbut[i].setGroup(g);
}
for(int i=0; i<12; i++)
if (c.equals(pal.elementAt(i))) {
curpal = i;
palbut[i].select();
break;
}
mid.add("South", midbot);
mid.add("North", ccube = new CbColorWindowCube(this));
add("Center", mid);
pack();
show();
setTitle("Choose Color...");
}
void updatePal(int i)
{
Graphics g = palimg[i].getGraphics();
g.setColor((Color)pal.elementAt(i));
g.fillRect(0, 0, 16, 16);
if (palbut[i] != null) palbut[i].repaint();
}
public void click(CbButton b)
{
if (b == ok) {
callback.chosen(this, col);
super.dispose();
}
else if (b == cancel)
dispose();
else {
for(int i=0; i<12; i++)
if (b == palbut[i]) {
curpal = i;
col = (Color)pal.elementAt(i);
ccube.red.setPosition(col.getRed());
ccube.blue.setPosition(col.getBlue());
ccube.green.setPosition(col.getGreen());
ccube.swatch.setColor(col);
}
}
}
public void dispose()
{
super.dispose();
callback.chosen(this, null);
}
public boolean isResizable() { return false; }
}
/**Displays 3 sliders, for red green and blue plus a block to show the
* current color
*/
class CbColorWindowCube extends BorderPanel implements CbSliderCallback
{
CbColorWindow parent;
CbSlider red, green, blue;
CbColorWindowSwatch swatch;
CbColorWindowCube(CbColorWindow p)
{
super(1, Util.body, Util.body);
parent = p;
setLayout(new BorderLayout());
Panel sl = new GrayPanel();
sl.setLayout(new GridLayout(3, 1));
sl.add(red = new CbSlider(0, 0, 255, p.col.getRed(), this));
sl.add(green = new CbSlider(0, 0, 255, p.col.getBlue(), this));
sl.add(blue = new CbSlider(0, 0, 255, p.col.getGreen(), this));
add("Center", sl);
add("East", swatch = new CbColorWindowSwatch(p.col));
}
public void moved(CbSlider s, int p)
{
moving(s, p);
}
public void moving(CbSlider s, int p)
{
parent.col = new Color(red.getPosition(), green.getPosition(),
blue.getPosition());
swatch.setColor(parent.col);
if (parent.curpal != -1) {
parent.pal.setElementAt(parent.col, parent.curpal);
parent.updatePal(parent.curpal);
}
}
}
interface CbColorWindowCallback
{
/**This method will be called when the user chooses a colour. If
* the user cancels the dialog, then this method will also be chosen
* but with null for the color.
*/
public void chosen(CbColorWindow w, Color c);
/**The chooser keeps a palette of colors that the user can modify,
* stored in a vector. The callback class should provide this vector
* so as to maintain the palette between color window calls.
* If an empty vector is returned, it will be filled with the default
* color table (which can be then modified).
* If null is returned, the chooser will use it's own internal
* vector.
*/
public Vector palette(CbColorWindow w);
}
class CbColorWindowSwatch extends BorderPanel
{
Color col = Color.black;
String txt;
CbColorWindowSwatch(Color c)
{
super(1);
setColor(c);
}
void setColor(Color c)
{
col = c;
txt = col.getRed()+","+col.getGreen()+","+col.getBlue();
repaint();
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(col);
g.fillRect(1, 1, size().width-2, size().height-2);
g.setColor(Color.white);
g.setXORMode(Color.black);
g.setFont(Util.f);
g.drawString(txt, 3, Util.fnm.getHeight()+1);
g.setPaintMode();
}
public void upate(Graphics g) { paint(g); }
public Dimension preferredSize()
{
return new Dimension(60, 60);
}
public Dimension minimumSize()
{
return preferredSize();
}
}

233
file/CbImageChooser.java Normal file
View File

@ -0,0 +1,233 @@
import java.awt.*;
import java.net.*;
class CbImageChooser extends Panel implements CbButtonCallback
{
Image img;
String imgsrc;
int imgw, imgh;
CbButton but;
CbImageFileWindow filewin;
//CbImageChooserCallback callback;
CbImageChooser(Image i)
{
this(i, null);
}
CbImageChooser(Image i, String s)
{
setLayout(new BorderLayout());
add("Center", but = new CbButton("Choose..", this));
setImage(i, s==null ? "" : s);
}
void setImage(Image i, String s)
{
img = i;
imgsrc = s;
if (img != null) but.setImage(img);
else but.setText("Choose..");
}
public void click(CbButton b)
{
if (b == but && filewin == null)
new CbImageFileWindow(this);
}
}
class CbImageFileWindow extends FixedFrame implements CbButtonCallback
{
CbImageChooser parent;
ScrollImage imgp;
TextField url;
CbButton browse, ok, cancel;
FileDialog filedlog;
String lastfile = "";
CbImageFileWindow(CbImageChooser p)
{
parent = p;
parent.filewin = this;
setLayout(new BorderLayout());
add("Center", imgp = new ScrollImage(parent.img, 200, 200));
Panel bot = new GrayPanel();
bot.setLayout(new FlowLayout(FlowLayout.LEFT));
bot.add(new Label("URL:"));
bot.add(url = new TextField(parent.imgsrc, 20));
bot.add(browse = new CbButton("Browse..", this));
bot.add(new Label(" "));
bot.add(ok = new CbButton("Ok", this));
bot.add(cancel = new CbButton("Cancel", this));
add("South", bot);
pack();
show();
setTitle("Choose Image..");
Util.recursiveBackground(this, Util.body);
}
public void click(CbButton b)
{
if (b == ok)
parent.setImage(imgp.img, lastfile);
if (b == ok || b == cancel)
dispose();
else if (b == browse) {
// Open file chooser here!
FileDialog filedlog =
new FileDialog(this, "Choose Image",FileDialog.LOAD);
filedlog.show();
if (filedlog.getFile() != null) {
// file chosen.. load it in
String fn = filedlog.getDirectory()+filedlog.getFile();
url.setText(fn);
loadFile(fn);
}
}
}
public void dispose()
{
super.dispose();
parent.filewin = null;
}
public boolean action(Event evt, Object obj)
{
if (evt.target == url) {
String ut = url.getText();
if (ut.startsWith("http:") || ut.startsWith("ftp:"))
loadURL(ut);
else
loadFile(ut);
return true;
}
return false;
}
private void loadFile(String f)
{
Image i = Util.tk.getImage(f);
if (i == null || !Util.waitForImage(i))
new ErrorWindow("Failed to load image "+f);
else {
imgp.setImage(i);
lastfile = f;
}
}
private void loadURL(String u)
{
try {
Image i = Util.tk.getImage(new URL(u));
if (i == null || !Util.waitForImage(i))
new ErrorWindow("Failed to load image from "+u);
else {
imgp.setImage(i);
lastfile = u;
}
}
catch(MalformedURLException e) {
new ErrorWindow(u+" is not a valid URL");
}
}
}
class ScrollImage extends Panel implements CbScrollbarCallback
{
Image img;
int imgw, imgh;
int pw, ph;
CbScrollbar vsc, hsc;
boolean compute_scrollbars = true;
ScrollImage(Image i)
{
this(i, Util.getWidth(i), Util.getHeight(i));
}
ScrollImage(Image i, int w, int h)
{
pw = w; ph = h;
setLayout(new BorderLayout());
add("East", vsc = new CbScrollbar(CbScrollbar.VERTICAL, this));
add("South", hsc = new CbScrollbar(CbScrollbar.HORIZONTAL, this));
setImage(i);
}
void setImage(Image i)
{
img = i;
if (img != null) {
imgw = Util.getWidth(img);
imgh = Util.getHeight(img);
}
compute_scrollbars = true;
repaint();
}
public void paint(Graphics g)
{
int w = size().width-vsc.size().width,
h = size().height-hsc.size().height;
if (compute_scrollbars) {
if (img == null) {
hsc.setValues(0, 1, 1);
vsc.setValues(0, 1, 1);
}
else {
if (imgw < w) hsc.setValues(0, 1, 1);
else hsc.setValues(0, w, imgw);
if (imgh < h) vsc.setValues(0, 1, 1);
else vsc.setValues(0, h, imgh);
}
compute_scrollbars = false;
}
g.setColor(Util.body);
g.fillRect(0, 0, w, h);
if (img != null) {
if (imgw < w && imgh < h)
g.drawImage(img, (w-imgw)/2, (h-imgh)/2, this);
else
g.drawImage(img, -hsc.getValue(), -vsc.getValue(),this);
}
else {
g.setFont(Util.f);
g.setColor(Util.text);
String s = "<None>";
g.drawString(s, (w-Util.fnm.stringWidth(s))/2,
(h-Util.fnm.getHeight())/2);
}
}
public void update(Graphics g) { paint(g); }
public void reshape(int nx, int ny, int nw, int nh)
{
super.reshape(nx, ny, nw, nh);
compute_scrollbars = true;
repaint();
}
public void moved(CbScrollbar s, int p)
{
repaint();
}
public void moving(CbScrollbar s, int p) { }
public Dimension minimumSize()
{
return new Dimension(pw, ph);
}
public Dimension preferredSize()
{
return minimumSize();
}
}

345
file/CbScrollbar.java Normal file
View File

@ -0,0 +1,345 @@
// CbScrollbar.java
// A drop-in replacement for the AWT scrollbar class, with callbacks
// and a nicer look. This scrollbar is typically used to display some
// fraction of a list of items, with values ranging from min to max.
// The lvisible parameter determines how many of the list are lvisible
// at any one time. The value of the scrollbar ranges from min to
// max-lvisible+1 (the highest position in the list to start displaying)
import java.awt.*;
public class CbScrollbar extends Panel
{
static final int VERTICAL = 0;
static final int HORIZONTAL = 1;
CbScrollbarCallback callback; // who to call back to
boolean inside, indent;
int orient; // horizontal or vertical?
int value; // position
int lvisible; // the number of lines lvisible
int num; // total number of lines
int lineinc = 1; // how much the arrow buttons move by
Color lc1 = Util.light_edge, lc2 = Util.body, lc3 = Util.dark_edge;
Color hc1 = Util.light_edge_hi, hc2 = Util.body_hi, hc3 = Util.dark_edge_hi;
Color bc = Util.dark_bg;
int y1, y2, x1, x2, drag;
CbScrollbarArrow arrow1, arrow2;
CbScrollbar(int o, CbScrollbarCallback cb)
{
this(o, 0, 1, 1, cb);
}
/**Create a new scrollbar
*/
CbScrollbar(int o, int v, int vis, int n, CbScrollbarCallback cb)
{
setValues(v, vis, n);
orient = o;
callback = cb;
setLayout(null);
if (orient == VERTICAL) {
add(arrow1 = new CbScrollbarArrow(this, 0));
add(arrow2 = new CbScrollbarArrow(this, 1));
}
else {
add(arrow1 = new CbScrollbarArrow(this, 2));
add(arrow2 = new CbScrollbarArrow(this, 3));
}
}
/**Set the current scrollbar parameters
* @param v Current position
* @param vis Number of lines lvisible
* @param n Total number of lines
*/
public void setValues(int v, int vis, int n)
{
value = v;
lvisible = vis;
num = n;
if (lvisible > num) lvisible = num;
checkValue();
repaint();
}
public int getValue() { return value; }
public void setValue(int v)
{
value = v;
checkValue();
repaint();
}
private void checkValue()
{
if (value < 0) value = 0;
else if (value > num-lvisible) value = num-lvisible;
}
public void paint(Graphics g)
{
if (num == 0) return;
int w = size().width, h = size().height;
boolean ins = inside && !(arrow1.inside || arrow2.inside);
Color c1 = ins ? hc1 : lc1, c2 = ins ? hc2 : lc2,
c3 = ins ? hc3 : lc3;
g.setColor(bc);
g.fillRect(0, 0, w, h);
g.setColor(c3);
g.drawLine(0, 0, w-1, 0); g.drawLine(0, 0, 0, h-1);
g.setColor(c1);
g.drawLine(w-1, h-1, w-1, 0); g.drawLine(w-1, h-1, 0, h-1);
if (orient == VERTICAL) {
int va = h-w*2;
y1 = w+va*value/num;
y2 = w+va*(value+lvisible)/num-1;
g.setColor(c2);
g.fillRect(1, y1, w-2, y2-y1);
g.setColor(indent ? c3 : c1);
g.drawLine(1, y1, w-2, y1);
g.drawLine(1, y1, 1, y2-1);
g.setColor(indent ? c1 : c3);
g.drawLine(w-2, y2-1, w-2, y1);
g.drawLine(w-2, y2-1, 1, y2-1);
if (ins) {
g.drawLine(w-3, y2-2, w-3, y1+1);
g.drawLine(w-3, y2-2, 2, y2-2);
}
}
else if (orient == HORIZONTAL) {
int va = w-h*2;
x1 = h+va*value/num;
x2 = h+va*(value+lvisible)/num-1;
g.setColor(c2);
g.fillRect(x1, 1, x2-x1, h-2);
g.setColor(indent ? c3 : c1);
g.drawLine(x1, 1, x1, h-2);
g.drawLine(x1, 1, x2-1, 1);
g.setColor(indent ? c1 : c3);
g.drawLine(x2-1, h-2, x1, h-2);
g.drawLine(x2-1, h-2, x2-1, 1);
if (ins) {
g.drawLine(x2-2, h-3, x1+1, h-3);
g.drawLine(x2-2, h-3, x2-2, 2);
}
}
}
/**Called by arrows to move the slider
*/
void arrowClick(int d)
{
int oldvalue = value;
value += d;
checkValue();
if (value != oldvalue) {
callback.moved(this, value);
repaint();
}
}
public void reshape(int nx, int ny, int nw, int nh)
{
super.reshape(nx, ny, nw, nh);
if (orient == VERTICAL) {
arrow1.reshape(1, 1, nw-2, nw-1);
arrow2.reshape(1, nh-nw-1, nw-2, nw-1);
}
else {
arrow1.reshape(1, 1, nh-1, nh-2);
arrow2.reshape(nw-nh-1, 1, nh-1, nh-2);
}
repaint();
}
public Dimension preferredSize()
{
return orient==VERTICAL ? new Dimension(16, 100)
: new Dimension(100, 16);
}
public Dimension minimumSize()
{
return preferredSize();
}
public boolean mouseDown(Event e, int mx, int my)
{
if (orient == VERTICAL) {
// move up/down one page, or start dragging
if (my < y1) arrowClick(-lvisible);
else if (my > y2) arrowClick(lvisible);
else {
indent = true;
drag = my-y1;
repaint();
}
}
else {
// move left/right one page, or start dragging
if (mx < x1) arrowClick(-lvisible);
else if (mx > x2) arrowClick(lvisible);
else {
indent = true;
drag = mx-x1;
repaint();
}
}
return true;
}
public boolean mouseDrag(Event e, int mx, int my)
{
if (indent) {
int w = size().width, h = size().height;
int oldvalue = value;
if (orient == VERTICAL) {
int va = h-w*2, ny = my-drag-w;
value = ny*num/va;
}
else {
int va = w-h*2, nx = mx-drag-h;
value = nx*num/va;
}
checkValue();
if (value != oldvalue) {
callback.moving(this, value);
repaint();
}
}
return indent;
}
public boolean mouseUp(Event e, int mx, int my)
{
if (indent) {
indent = false;
repaint();
callback.moved(this, value);
return true;
}
return false;
}
/*
public boolean mouseEnter(Event e, int mx, int my)
{
inside = true;
repaint();
return true;
}
public boolean mouseExit(Event e, int mx, int my)
{
inside = false;
repaint();
return true;
}
*/
}
class CbScrollbarArrow extends Canvas implements Runnable
{
int mode;
CbScrollbar scrollbar;
boolean inside, indent;
Thread th;
CbScrollbarArrow(CbScrollbar p, int m)
{
scrollbar = p;
mode = m;
}
public void paint(Graphics g)
{
int w = size().width, h = size().height;
Color c1 = inside ? scrollbar.hc1 : scrollbar.lc1,
c2 = inside ? scrollbar.hc2 : scrollbar.lc2,
c3 = inside ? scrollbar.hc3 : scrollbar.lc3;
g.setColor(scrollbar.bc);
g.fillRect(0, 0, w, h);
int xp[] = new int[3], yp[] = new int[3];
// blank, dark, light
if (mode == 0) {
// up arrow
xp[0] = w/2; xp[1] = w-1; xp[2] = 0;
yp[0] = 0; yp[1] = h-1; yp[2] = h-1;
}
else if (mode == 1) {
// down arrow
xp[0] = 0; xp[1] = w/2; xp[2] = w-1;
yp[0] = 0; yp[1] = h-1; yp[2] = 0;
}
else if (mode == 2) {
// left arrow
xp[0] = 0; xp[1] = w-1; xp[2] = w-1;
yp[0] = h/2; yp[1] = h-1; yp[2] = 0;
}
else if (mode == 3) {
// right arrow
xp[0] = 0; xp[1] = w-1; xp[2] = 0;
yp[0] = 0; yp[1] = h/2; yp[2] = h-1;
}
g.setColor(c2);
g.fillPolygon(xp, yp, 3);
g.setColor(indent ? c1 : c3);
g.drawLine(xp[1], yp[1], xp[2], yp[2]);
g.setColor(indent ? c3 : c1);
g.drawLine(xp[0], yp[0], xp[2], yp[2]);
}
public boolean mouseDown(Event e, int mx, int my)
{
indent = true;
repaint();
(th = new Thread(this)).start();
return true;
}
public boolean mouseUp(Event e, int mx, int my)
{
indent = false;
repaint();
if (th != null) th.stop();
return true;
}
/**Thread for doing repeated scrolling
*/
public void run()
{
int stime = 500;
while(true) {
scrollbar.arrowClick(mode%2 == 0 ? -1 : 1);
try { Thread.sleep(stime); } catch(Exception e) { }
stime = 100;
}
}
}
// CbScrollbarCallback
// Methods for reporting the movement of the scrollbar to another object
interface CbScrollbarCallback
{
/**Called when the scrollbar stops moving. This happens when an
* arrow is clicked, the scrollbar is moved by a page, or the user
* lets go of the scrollbar after dragging it.
* @param sb The scrollar that has been moved
* @param v The new value
*/
void moved(CbScrollbar sb, int v);
/**Called upon every pixel movement of the scrollbar when it is
* being dragged, but NOT when moved() is called.
* @param sb The scrollar that has been moved
* @param v The new value
*/
void moving(CbScrollbar sb, int v);
}

233
file/CbSlider.java Normal file
View File

@ -0,0 +1,233 @@
import java.awt.*;
class CbSlider extends Canvas
{
int dir, min, max, pos;
CbSliderCallback callback;
int px, py;
Color lc1 = Util.light_edge, lc2 = Util.body, lc3 = Util.dark_edge;
Color hc1 = Util.light_edge_hi, hc2 = Util.body_hi, hc3 = Util.dark_edge_hi;
int ticks = 0;
boolean inside = false, dragging = false;
int dragx;
/**Create a new slider
* @param d 0=horizontal, 1=vertical
* @param mi Minimum value
* @param ma Maximum value
* @param p Current value
*/
public CbSlider(int d, int mi, int ma, int p)
{
this(d, mi, ma, p, null);
}
/**Create a new slider
* @param d 0=horizontal, 1=vertical
* @param mi Minimum value
* @param ma Maximum value
* @param p Current value
* @param cb Object to call back to
*/
public CbSlider(int d, int mi, int ma, int p, CbSliderCallback cb)
{
dir = d; min = mi; max = ma;
pos = p;
callback = cb;
}
/**Toggle drawing of tick-marks on the slider track
* @param t The number of units/tick, or 0 to disable
*/
public void setTicks(int t)
{
ticks = t;
repaint();
}
/**Returns the current slider position
*/
public int getPosition() { return pos; }
/**Sets the current slider position
*/
public void setPosition(int p)
{
if (pos != p) {
pos = p;
repaint();
}
}
/**Returns the current minimum slider value
*/
public int getMinimum() { return min; }
/**Sets the minimum slider value
* @param mi The new minimum
*/
public void setMinimum(int mi)
{
min = mi;
checkPos();
repaint();
}
/**Returns the current maximum slider value
*/
public int getMaximum() { return max; }
/**Sets the maximum slider value
* @param mx The new maximum
*/
public void setMaximum(int mx)
{
max = mx;
checkPos();
repaint();
}
public void paint(Graphics g)
{
Color c1 = inside ? hc1 : lc1,
c2 = inside ? hc2 : lc2,
c3 = inside ? hc3 : lc3;
// draw slider track
int w = size().width, h = size().height;
g.setColor(c2);
g.fillRect(0, 0, w, h);
g.setColor(c3);
g.drawLine(8, h/2, w-8, h/2);
g.setColor(c1);
g.drawLine(8, h/2+1, w-8, h/2+1);
// draw border
g.setColor(c1);
g.drawLine(0, 0, w-1, 0);
g.drawLine(0, 0, 0, h-1);
g.setColor(c3);
g.drawLine(w-1, h-1, w-1, 0);
g.drawLine(w-1, h-1, 0, h-1);
if (inside) {
g.drawLine(w-2, h-2, w-2, 0);
g.drawLine(w-2, h-2, 0, h-2);
}
// draw tick marks
if (ticks != 0) {
int mm = max-min;
for(int i=0; i<=mm; i+=ticks) {
int tx = ((w-16)*i / mm) + 8;
g.setColor(c3);
g.drawLine(tx, h/2, tx, h/2-6);
}
}
// draw slider
px = ((w-16)*pos / (max - min)) + 8;
py = h/2;
g.setColor(c2);
int xpt[] = { px-3, px-3, px, px+3, px+3 };
int ypt[] = { py+5, py-4, py-6, py-4, py+5 };
g.fillPolygon(xpt, ypt, 5);
g.setColor(dragging ? c3 : c1);
g.drawLine(px-3, py+5, px-3, py-4);
g.drawLine(px-3, py-4, px, py-6);
g.setColor(dragging ? c1 : c3);
g.drawLine(px-3, py+5, px+3, py+5);
g.drawLine(px+3, py+5, px+3, py-4);
}
public void update(Graphics g) { paint(g); }
public boolean mouseEnter(Event e, int x, int y)
{
inside = true;
repaint();
return true;
}
public boolean mouseDown(Event e, int x, int y)
{
int step = ticks==0 ? (max-min)/10 : ticks;
if (x < px-3) {
// move one tick to the left
pos -= step;
}
else if (x > px+3) {
// move one tick to the right
pos += step;
}
else {
// start dragging
dragging = true;
dragx = x-px;
}
checkPos();
if (callback != null)
callback.moved(this, pos);
repaint();
return true;
}
public boolean mouseDrag(Event e, int x, int y)
{
if (dragging) {
px = x-dragx;
pos = (px-8)*(max - min) / (size().width-16);
checkPos();
if (callback != null)
callback.moving(this, pos);
repaint();
}
return dragging;
}
public boolean mouseUp(Event e, int x, int y)
{
if (dragging) {
dragging = false;
if (callback != null)
callback.moved(this, pos);
repaint();
return true;
}
return false;
}
public boolean mouseExit(Event e, int x, int y)
{
inside = false;
repaint();
return true;
}
protected void checkPos()
{
if (pos < min) pos = min;
else if (pos > max) pos = max;
}
public Dimension preferredSize()
{
return new Dimension(100, 20);
}
public Dimension minimumSize() { return preferredSize(); }
}
interface CbSliderCallback
{
/**Callled back when the slider stops at a new position
* @param s The slider being moved
* @param p New position
*/
public void moved(CbSlider s, int p);
/**Callled back whenever the slider is being dragged
* @param s The slider being moved
* @param p New position
*/
public void moving(CbSlider s, int p);
}

34
file/ErrorWindow.java Normal file
View File

@ -0,0 +1,34 @@
import java.awt.*;
import java.util.*;
class ErrorWindow extends FixedFrame implements CbButtonCallback
{
CbButton ok;
ErrorWindow(String m)
{
setLayout(new BorderLayout());
Panel cen = new BorderPanel(1);
StringTokenizer tok = new StringTokenizer(m, "\r\n");
cen.setLayout(new GridLayout(tok.countTokens(), 1));
while(tok.hasMoreTokens()) {
cen.add(new Label(tok.nextToken()));
}
add("Center", cen);
Panel bot = new GrayPanel();
bot.setLayout(new FlowLayout(FlowLayout.CENTER));
bot.add(new CbButton("Ok", this));
add("South", bot);
pack();
show();
setTitle("Error");
Util.recursiveBackground(this, Util.body);
}
public void click(CbButton b)
{
dispose();
}
}

4504
file/FileManager.java Normal file

File diff suppressed because it is too large Load Diff

3497
file/FileManager.java.bak Normal file

File diff suppressed because it is too large Load Diff

46
file/FixedFrame.java Normal file
View File

@ -0,0 +1,46 @@
import java.awt.*;
import java.io.*;
public class FixedFrame extends Frame
{
int mw = 0, mh = 0;
public FixedFrame()
{
Dimension d = Util.tk.getScreenSize();
double rx = Math.random(), ry = Math.random();
move((int)((d.width/2)*rx), (int)((d.height/2)*ry));
}
public FixedFrame(int w, int h)
{
this();
mw = w; mh = h;
}
public boolean handleEvent(Event evt)
{
if (evt.target == this && evt.id == Event.WINDOW_DESTROY) {
dispose();
return true;
}
return super.handleEvent(evt);
}
public Dimension minimumSize()
{
if (mw != 0 && mh != 0) return new Dimension(mw, mh);
else return super.minimumSize();
}
public Dimension preferredSize()
{
return minimumSize();
}
public void setFixedSize(int w, int h)
{
mw = w; mh = h;
}
}

10
file/GrayPanel.java Normal file
View File

@ -0,0 +1,10 @@
import java.awt.*;
public class GrayPanel extends Panel
{
public void paint(Graphics g)
{
g.setColor(Util.body);
g.fillRect(0, 0, size().width, size().height);
}
}

345
file/Hierarchy.java Normal file
View File

@ -0,0 +1,345 @@
// Hierarchy
// An AWT component for displaying a tree-like heirachy, with each node
// having an icon and a name. This heirachy can be expanded or contracted
// by the user.
import java.awt.*;
import java.util.Vector;
public class Hierarchy extends BorderPanel implements CbScrollbarCallback
{
HierarchyNode root; // the root of the tree
CbScrollbar sb; // scrollbar at right
int width, height; // usable drawing area
int sbwidth; // size of scrollbar
HierarchyCallback callback; // who to call on open / close
Image bim; // double-buffer image
Font font = new Font("courier", Font.PLAIN, 12);
FontMetrics fnm; // size of font used
Graphics bg; // back-images graphics
int top = 0; // top-most row displayed
int count = 0; // total rows in the tree
Insets in; // insets from border
HierarchyNode sel; // selected node
long last; // time of last mouse click
static boolean broken_awt = System.getProperty("os.name").
startsWith("Windows");
// Create a new Hierarchy object with the given root
Hierarchy(HierarchyNode r)
{
this();
root = r;
}
// Create a new Hierarchy object that calls back to the given object
// when nodes are clicked on.
Hierarchy(HierarchyNode r, HierarchyCallback c)
{
this(r);
callback = c;
}
// Create an empty hierarchy object, with no callback
Hierarchy()
{
super(3, Util.dark_edge_hi, Util.body_hi);
// Create UI
setLayout(null);
sb = new CbScrollbar(CbScrollbar.VERTICAL, this);
add(sb);
}
// Create an empty hierarchy object, set to report user actions to
// the given object.
Hierarchy(HierarchyCallback c)
{
this();
callback = c;
}
// redraw
// Called by the using class when the tree passed to this object
// changes, to force a redraw and resizing of the scrollbar
void redraw()
{
if (fnm != null) {
render();
paint(getGraphics());
compscroll();
}
}
// setRoot
// Set the root node for this hierarchy
void setRoot(HierarchyNode r)
{
root = r;
redraw();
}
// selected
// Return the currently selected node, or null
HierarchyNode selected()
{
return sel;
}
// select
// Selected the given node
void select(HierarchyNode s)
{
sel = s;
}
// force the use of some font
public void setFont(Font f)
{
font = f;
bim = null;
repaint();
}
// reshape
// Called when this component gets resized
public void reshape(int nx, int ny, int nw, int nh)
{
in = insets();
sbwidth = sb.minimumSize().width;
width = nw-sbwidth - (in.left + in.right);
height = nh - (in.top + in.bottom);
sb.reshape(width+in.left, in.top, sbwidth, height);
// force creation of a new backing images
bim = null;
repaint();
compscroll();
super.reshape(nx, ny, nw, nh);
}
// update
// Called sometime after repaint()
public void update(Graphics g)
{
render();
paint(g);
}
// paint
// Blit the backing image to the front
public void paint(Graphics g)
{
super.paint(g);
if (bim == null) {
// This is the first rendering
bim = createImage(width, height);
bg = bim.getGraphics();
bg.setFont(font);
fnm = bg.getFontMetrics();
render();
compscroll();
}
g.drawImage(bim, in.left, in.top, this);
}
// mouseDown
// Called upon a mouseclick
public boolean mouseDown(Event evt, int x, int y)
{
if (root == null)
return false; // nothing to do
HierarchyNode s = nodeat(root, x/16, (y/16)+top);
if (s == null) {
// Just deselect
sel = null;
repaint();
return true;
}
// Check for double-click
boolean dc = false;
if (evt.when-last < 500 && sel == s)
dc = true;
else
last = evt.when;
sel = s;
if (dc && sel.ch != null) {
// Open or close this node
sel.open = !sel.open;
if (callback != null) {
// Notify callback, which MAY do something to change
// the structure of the tree
if (sel.open) callback.openNode(this, sel);
else callback.closeNode(this, sel);
}
}
else if (callback != null) {
// Single click on a node or double-click on leaf node
if (dc) callback.doubleNode(this, sel);
else callback.clickNode(this, sel);
}
compscroll();
repaint();
return true;
}
public void moved(CbScrollbar s, int v)
{
moving(s, v);
}
public void moving(CbScrollbar s, int v)
{
top = sb.getValue();
compscroll();
repaint();
}
// render
// Draw the current tree view into the backing image
private void render()
{
if (fnm != null) {
int fh = fnm.getHeight(), // useful font metrics
fa = fnm.getAscent();
bg.setColor(Util.light_bg);
bg.fillRect(0, 0, width, height);
if (root == null)
return; // nothing to do
bg.setColor(Util.text);
recurse(root, 0, 0, fh, fa);
}
}
// recurse
// Render a node in the tree at the given location, maybe followed
// by all it's children. Return the number of rows this node took
// to display.
private int recurse(HierarchyNode n, int x, int y, int fh, int fa)
{
int xx = x*16, yy = (y-top)*16;
int len = 1;
n.x = x;
n.y = y;
int tw = fnm.stringWidth(n.text);
if (yy >= 0 && yy <= height) {
// Draw this node
if (n.im != null)
bg.drawImage(n.im, xx, yy, this);
if (sel == n) {
// Select this node
bg.setColor(Util.body);
bg.fillRect(xx+17, yy+2, tw+2, 13);
bg.setColor(Util.text);
}
bg.drawString(n.text, xx+18, yy+12);
}
if (n.ch != null && n.open && yy <= height) {
// Mark this node
bg.drawLine(xx+18, yy+14, xx+17+tw, yy+14);
// Draw subnodes
yy += 16;
for(int i=0; i<n.ch.size() && yy<=height; i++) {
int l=recurse((HierarchyNode)n.ch.elementAt(i),
x+1, y+len, fh, fa);
bg.drawLine(xx+7, yy+7, xx+15, yy+7);
if (i == n.ch.size()-1)
bg.drawLine(xx+7, yy, xx+7, yy+7);
else
bg.drawLine(xx+7, yy, xx+7,yy+(l*16)-1);
len += l;
yy += l*16;
}
}
return len;
}
// compscroll
// Re-compute scrollbar size
private void compscroll()
{
if (fnm == null)
return;
int ct = root!=null ? count(root) : 1;
int r = Math.min(ct, height/16 - 1);
int c = ct - r;
//sb.setValues(top, r==0?1:r, c<0?0:c);
sb.setValues(top, r==0?1:r, ct);
}
// count
// Returns the number of visible rows from a node
private int count(HierarchyNode n)
{
int l = 1;
if (n.open && n.ch != null)
for(int i=0; i<n.ch.size(); i++)
l += count((HierarchyNode)n.ch.elementAt(i));
return l;
}
// nodeat
// Is the given node at the given position? If not, check its
// children too.
private HierarchyNode nodeat(HierarchyNode n, int x, int y)
{
if (y == n.y && x >= n.x)
return n;
if (n.ch == null || !n.open)
return null;
for(int i=0; i<n.ch.size(); i++) {
HierarchyNode c = nodeat((HierarchyNode)n.ch.elementAt(i),x,y);
if (c != null) return c;
}
return null;
}
}
// HierarchyNode
// One node in the tree displayed by the Hierarchy object.
class HierarchyNode
{
boolean open; // is this node open?
Image im; // icon for this node (assumed to be 16x16!)
Vector ch; // sub-nodes of this one, or null
String text; // name of this node
int x, y; // row/column in list
HierarchyNode() { }
HierarchyNode(boolean o, Image i, Vector c, String t)
{
open = o;
im = i;
ch = c;
text = t;
}
}
// HierarchyCallback
// Programmers using the Hierarchy class pass an object that implements the
// HierarchyCallback interface to its constructor, to receive information
// about user actions.
interface HierarchyCallback
{
// openNode
// Called when a node with children is opened
void openNode(Hierarchy h, HierarchyNode n);
// closeNode
// Called when a node is closed
void closeNode(Hierarchy h, HierarchyNode n);
// clickNode
// Called when the user clicks on a node
void clickNode(Hierarchy h, HierarchyNode n);
// doubleNode
// Called when a user double-clicks on a node
void doubleNode(Hierarchy h, HierarchyNode n);
}

345
file/Hierarchy.java.bak Normal file
View File

@ -0,0 +1,345 @@
// Hierarchy
// An AWT component for displaying a tree-like heirachy, with each node
// having an icon and a name. This heirachy can be expanded or contracted
// by the user.
import java.awt.*;
import java.util.Vector;
public class Hierarchy extends BorderPanel implements CbScrollbarCallback
{
HierarchyNode root; // the root of the tree
CbScrollbar sb; // scrollbar at right
int width, height; // usable drawing area
int sbwidth; // size of scrollbar
HierarchyCallback callback; // who to call on open / close
Image bim; // double-buffer image
Font font = new Font("courier", Font.PLAIN, 12);
FontMetrics fnm; // size of font used
Graphics bg; // back-images graphics
int top = 0; // top-most row displayed
int count = 0; // total rows in the tree
Insets in; // insets from border
HierarchyNode sel; // selected node
long last; // time of last mouse click
static boolean broken_awt = System.getProperty("os.name").
startsWith("Windows");
// Create a new Hierarchy object with the given root
Hierarchy(HierarchyNode r)
{
this();
root = r;
}
// Create a new Hierarchy object that calls back to the given object
// when nodes are clicked on.
Hierarchy(HierarchyNode r, HierarchyCallback c)
{
this(r);
callback = c;
}
// Create an empty hierarchy object, with no callback
Hierarchy()
{
super(3, new Color(50,50,50), new Color(220,220,220));
// Create UI
setLayout(null);
sb = new CbScrollbar(CbScrollbar.VERTICAL, this);
add(sb);
}
// Create an empty hierarchy object, set to report user actions to
// the given object.
Hierarchy(HierarchyCallback c)
{
this();
callback = c;
}
// redraw
// Called by the using class when the tree passed to this object
// changes, to force a redraw and resizing of the scrollbar
void redraw()
{
if (fnm != null) {
render();
paint(getGraphics());
compscroll();
}
}
// setRoot
// Set the root node for this hierarchy
void setRoot(HierarchyNode r)
{
root = r;
redraw();
}
// selected
// Return the currently selected node, or null
HierarchyNode selected()
{
return sel;
}
// select
// Selected the given node
void select(HierarchyNode s)
{
sel = s;
}
// force the use of some font
void setFont(Font f)
{
font = f;
bim = null;
repaint();
}
// reshape
// Called when this component gets resized
public void reshape(int nx, int ny, int nw, int nh)
{
in = insets();
sbwidth = sb.minimumSize().width;
width = nw-sbwidth - (in.left + in.right);
height = nh - (in.top + in.bottom);
sb.reshape(width+in.left, in.top, sbwidth, height);
// force creation of a new backing images
bim = null;
repaint();
compscroll();
super.reshape(nx, ny, nw, nh);
}
// update
// Called sometime after repaint()
public void update(Graphics g)
{
render();
paint(g);
}
// paint
// Blit the backing image to the front
public void paint(Graphics g)
{
super.paint(g);
if (bim == null) {
// This is the first rendering
bim = createImage(width, height);
bg = bim.getGraphics();
bg.setFont(font);
fnm = bg.getFontMetrics();
render();
compscroll();
}
g.drawImage(bim, in.left, in.top, this);
}
// mouseDown
// Called upon a mouseclick
public boolean mouseDown(Event evt, int x, int y)
{
if (root == null)
return false; // nothing to do
HierarchyNode s = nodeat(root, x/16, (y/16)+top);
if (s == null) {
// Just deselect
sel = null;
repaint();
return true;
}
// Check for double-click
boolean dc = false;
if (evt.when-last < 500 && sel == s)
dc = true;
else
last = evt.when;
sel = s;
if (dc && sel.ch != null) {
// Open or close this node
sel.open = !sel.open;
if (callback != null) {
// Notify callback, which MAY do something to change
// the structure of the tree
if (sel.open) callback.openNode(this, sel);
else callback.closeNode(this, sel);
}
}
else if (callback != null) {
// Single click on a node or double-click on leaf node
if (dc) callback.doubleNode(this, sel);
else callback.clickNode(this, sel);
}
compscroll();
repaint();
return true;
}
public void moved(CbScrollbar s, int v)
{
moving(s, v);
}
public void moving(CbScrollbar s, int v)
{
top = sb.getValue();
compscroll();
repaint();
}
// render
// Draw the current tree view into the backing image
private void render()
{
if (fnm != null) {
int fh = fnm.getHeight(), // useful font metrics
fa = fnm.getAscent();
bg.setColor(Color.white);
bg.fillRect(0, 0, width, height);
if (root == null)
return; // nothing to do
bg.setColor(Color.black);
recurse(root, 0, 0, fh, fa);
}
}
// recurse
// Render a node in the tree at the given location, maybe followed
// by all it's children. Return the number of rows this node took
// to display.
private int recurse(HierarchyNode n, int x, int y, int fh, int fa)
{
int xx = x*16, yy = (y-top)*16;
int len = 1;
n.x = x;
n.y = y;
int tw = fnm.stringWidth(n.text);
if (yy >= 0 && yy <= height) {
// Draw this node
if (n.im != null)
bg.drawImage(n.im, xx, yy, this);
if (sel == n) {
// Select this node
bg.setColor(Color.lightGray);
bg.fillRect(xx+17, yy+2, tw+2, 13);
bg.setColor(Color.black);
}
bg.drawString(n.text, xx+18, yy+12);
}
if (n.ch != null && n.open && yy <= height) {
// Mark this node
bg.drawLine(xx+18, yy+14, xx+17+tw, yy+14);
// Draw subnodes
yy += 16;
for(int i=0; i<n.ch.size() && yy<=height; i++) {
int l=recurse((HierarchyNode)n.ch.elementAt(i),
x+1, y+len, fh, fa);
bg.drawLine(xx+7, yy+7, xx+15, yy+7);
if (i == n.ch.size()-1)
bg.drawLine(xx+7, yy, xx+7, yy+7);
else
bg.drawLine(xx+7, yy, xx+7,yy+(l*16)-1);
len += l;
yy += l*16;
}
}
return len;
}
// compscroll
// Re-compute scrollbar size
private void compscroll()
{
if (fnm == null)
return;
int ct = root!=null ? count(root) : 1;
int r = Math.min(ct, height/16 - 1);
int c = ct - r;
//sb.setValues(top, r==0?1:r, c<0?0:c);
sb.setValues(top, r==0?1:r, ct);
}
// count
// Returns the number of visible rows from a node
private int count(HierarchyNode n)
{
int l = 1;
if (n.open && n.ch != null)
for(int i=0; i<n.ch.size(); i++)
l += count((HierarchyNode)n.ch.elementAt(i));
return l;
}
// nodeat
// Is the given node at the given position? If not, check its
// children too.
private HierarchyNode nodeat(HierarchyNode n, int x, int y)
{
if (y == n.y && x >= n.x)
return n;
if (n.ch == null || !n.open)
return null;
for(int i=0; i<n.ch.size(); i++) {
HierarchyNode c = nodeat((HierarchyNode)n.ch.elementAt(i),x,y);
if (c != null) return c;
}
return null;
}
}
// HierarchyNode
// One node in the tree displayed by the Hierarchy object.
class HierarchyNode
{
boolean open; // is this node open?
Image im; // icon for this node (assumed to be 16x16!)
Vector ch; // sub-nodes of this one, or null
String text; // name of this node
int x, y; // row/column in list
HierarchyNode() { }
HierarchyNode(boolean o, Image i, Vector c, String t)
{
open = o;
im = i;
ch = c;
text = t;
}
}
// HierarchyCallback
// Programmers using the Hierarchy class pass an object that implements the
// HierarchyCallback interface to its constructor, to receive information
// about user actions.
interface HierarchyCallback
{
// openNode
// Called when a node with children is opened
void openNode(Hierarchy h, HierarchyNode n);
// closeNode
// Called when a node is closed
void closeNode(Hierarchy h, HierarchyNode n);
// clickNode
// Called when the user clicks on a node
void clickNode(Hierarchy h, HierarchyNode n);
// doubleNode
// Called when a user double-clicks on a node
void doubleNode(Hierarchy h, HierarchyNode n);
}

39
file/LinedPanel.java Normal file
View File

@ -0,0 +1,39 @@
import java.awt.*;
class LinedPanel extends GrayPanel
{
String title;
LinedPanel(String t)
{
title = t;
}
public void paint(Graphics g)
{
super.paint(g);
Font f = g.getFont();
FontMetrics fnm = g.getFontMetrics();
int w = size().width-1, h = size().height - 1;
int tl = fnm.stringWidth(title);
g.setColor(Util.light_edge);
g.drawLine(5, 5, 5, h-5);
g.drawLine(5, h-5, w-5, h-5);
g.drawLine(w-5, h-5, w-5, 5);
g.drawLine(tl+9, 5, w-5, 5);
g.setColor(Util.dark_edge);
g.drawLine(4, 4, 4, h-6);
g.drawLine(6, h-6, w-6, h-6);
g.drawLine(w-6, h-6, w-6, 6);
g.drawLine(w-6, 4, tl+9, 4);
g.drawString(title, 7, fnm.getAscent());
}
public Insets insets()
{
return new Insets(15, 10, 10, 10);
}
}

4
file/Makefile Normal file
View File

@ -0,0 +1,4 @@
file.jar: FileManager.java Util.java
CLASSPATH=/usr/local/netscape7/plugins/java2/lib/javaplugin.jar:. javac -target 1.1 *.java
jar cf file.jar *.class
[ -d "../zomos-virtual" ] && jar cf ../zomos-virtual/file.jar *.class

583
file/MultiColumn.java Normal file
View File

@ -0,0 +1,583 @@
// MultiColumn
// A List box that supports multiple columns.
import java.awt.*;
import java.util.Vector;
public class MultiColumn extends BorderPanel implements CbScrollbarCallback
{
MultiColumnCallback callback; // what to call back to
String title[]; // column titles
boolean adjustable = true;
boolean drawlines = true;
Color colors[][] = null;
boolean enabled = true;
boolean multiselect = false;
int cpos[]; // column x positions
float cwidth[]; // proportional column widths
Vector list[]; // columns of the list
CbScrollbar sb; // scrollbar at the right side
int width, height; // size, minus the scrollbar
Insets in; // used space around the border
int sbwidth; // width of the scrollbar
int th; // height of title bar
Image bim; // backing image
Graphics bg; // backing graphics
Font font = new Font("timesRoman", Font.PLAIN, 12);
FontMetrics fnm; // drawing font size
int coldrag = -1; // column being resized
int sel = -1; // selected row
int sels[] = new int[0]; // all selected rows
int top = 0; // first row displayed
long last; // last mouse click time
int rowh = 16; // row height
Event last_event; // last event that triggered callback
int sortcol; // Column currently being sorted
int sortdir; // Sort direction (0=none, 1=up, 2=down)
// Create a new list with the given column titles
MultiColumn(String t[])
{
super(3, Util.dark_edge_hi, Util.body_hi);
title = new String[t.length];
for(int i=0; i<t.length; i++)
title[i] = t[i];
list = new Vector[t.length];
for(int i=0; i<t.length; i++)
list[i] = new Vector();
cwidth = new float[t.length];
for(int i=0; i<t.length; i++)
cwidth[i] = 1.0f/t.length;
cpos = new int[t.length+1];
setLayout(null);
sb = new CbScrollbar(CbScrollbar.VERTICAL, this);
add(sb);
}
// Create a new list that calls back to the given object on
// single or double clicks.
MultiColumn(String t[], MultiColumnCallback c)
{
this(t);
callback = c;
}
// addItem
// Add a row to the list
void addItem(Object item[])
{
for(int i=0; i<title.length; i++)
list[i].addElement(item[i]);
repaint();
compscroll();
}
// addItems
// Add several rows to the list
void addItems(Object item[][])
{
for(int i=0; i<item.length; i++)
for(int j=0; j<title.length; j++)
list[j].addElement(item[i][j]);
repaint();
compscroll();
}
// modifyItem
// Changes one row of the table
void modifyItem(Object item[], int row)
{
for(int i=0; i<title.length; i++)
list[i].setElementAt(item[i], row);
repaint();
compscroll();
}
// getItem
// Returns the contents of a given row
Object []getItem(int n)
{
Object r[] = new Object[title.length];
for(int i=0; i<title.length; i++)
r[i] = list[i].elementAt(n);
return r;
}
// selected
// Return the most recently selected row
int selected()
{
return sel;
}
// select
// Select some row
void select(int s)
{
sel = s;
sels = new int[1];
sels[0] = s;
repaint();
}
// select
// Select multiple rows
void select(int s[])
{
if (s.length == 0) {
sel = -1;
sels = new int[0];
}
else {
sel = s[0];
sels = s;
}
repaint();
}
// allSelected
// Returns all the selected rows
int[] allSelected()
{
return sels;
}
// scrollto
// Scroll to make some row visible
void scrollto(int s)
{
int r = rows();
if (s < top || s >= top+r) {
top = s-1;
if (top > list[0].size() - r)
top = list[0].size() - r;
sb.setValue(top);
repaint();
}
}
// deleteItem
// Remove one row from the list
void deleteItem(int n)
{
for(int i=0; i<title.length; i++)
list[i].removeElementAt(n);
if (n == sel) {
// De-select deleted file
sel = -1;
}
for(int i=0; i<sels.length; i++) {
if (sels[i] == n) {
// Remove from selection list
int nsels[] = new int[sels.length-1];
if (nsels.length > 0) {
System.arraycopy(sels, 0, nsels, 0, i);
System.arraycopy(sels, i+1, nsels, i,
nsels.length-i);
sel = nsels[0];
}
break;
}
}
repaint();
compscroll();
}
// clear
// Remove everything from the list
void clear()
{
for(int i=0; i<title.length; i++)
list[i].removeAllElements();
sel = -1;
sels = new int[0];
top = 0;
repaint();
sb.setValues(0, 1, 0);
}
// setWidths
// Set the proportional widths of each column
void setWidths(float w[])
{
for(int i=0; i<title.length; i++)
cwidth[i] = w[i];
respace();
repaint();
}
/**Turns on or off the user's ability to adjust column widths
* @param a Can adjust or not?
*/
void setAdjustable(boolean a)
{
adjustable = a;
}
/**Turns on or off the drawing of column lines
* @param d Draw lines or not?
*/
void setDrawLines(boolean d)
{
drawlines = d;
}
/**Sets the array of colors used to draw text items.
* @param c The color array (in row/column order), or null to
* use the default
*/
void setColors(Color c[][])
{
colors = c;
repaint();
}
// Turns on or off multi-row selection with ctrl and shift
void setMultiSelect(boolean m)
{
multiselect = m;
}
// Enables the entire list
public void enable()
{
enabled = true;
sb.enable();
repaint();
}
// Disables the entire list
public void disable()
{
enabled = false;
sb.disable();
repaint();
}
// Sets or turns off the sort indication arrow for a column
// Direction 0 = None, 1 = Up arrow, 2 = Down arrow
public void sortingArrow(int col, int dir)
{
sortcol = col;
sortdir = dir;
repaint();
}
public void setFont(Font f)
{
font = f;
bim = null;
repaint();
}
// reshape
// Called when this component gets resized
public void reshape(int nx, int ny, int nw, int nh)
{
if (nw != width+sbwidth || nh != height) {
in = insets();
sbwidth = sb.minimumSize().width;
width = nw-sbwidth - (in.left + in.right);
height = nh - (in.top + in.bottom);
sb.reshape(width+in.left, in.top, sbwidth, height);
respace();
// Force creation of a new backing image and re-painting
bim = null;
repaint();
compscroll();
}
super.reshape(nx, ny, nw, nh);
}
// respace
// Compute pixel column widths from proportional widths
void respace()
{
cpos[0] = 0;
for(int i=0; i<title.length; i++)
cpos[i+1] = cpos[i] + (int)(width*cwidth[i]);
}
// paint
// Blit the backing image to the front
public void paint(Graphics g)
{
super.paint(g);
if (bim == null) {
// This is the first rendering
bim = createImage(width, height);
bg = bim.getGraphics();
bg.setFont(font);
fnm = bg.getFontMetrics();
th = fnm.getHeight() + 4;
render();
compscroll();
}
g.drawImage(bim, in.left, in.top, this);
}
// update
// Called sometime after repaint()
public void update(Graphics g)
{
if (fnm != null) {
render();
paint(g);
}
}
// render
// Re-draw the list into the backing image
void render()
{
int fh = fnm.getHeight(), // useful font metrics
fd = fnm.getDescent(),
fa = fnm.getAscent();
int bot = Math.min(top+rows()-1, list[0].size()-1);
// Clear title section and list
bg.setColor(Util.body);
bg.fillRect(0, 0, width, th);
bg.setColor(Util.light_bg);
bg.fillRect(0, th, width, height-th);
Color lighterGray = Util.body_hi;
if (enabled) {
// Mark the selected rows
for(int i=0; i<sels.length; i++) {
if (sels[i] >= top && sels[i] <= bot) {
bg.setColor(sels[i] == sel ? Util.body
: lighterGray);
bg.fillRect(0, th+(sels[i]-top)*rowh,
width, rowh);
}
}
}
// Draw each column
for(int i=0; i<title.length; i++) {
int x = cpos[i], w = cpos[i+1]-x-1;
// Column title
bg.setColor(Util.light_edge);
bg.drawLine(x, 0, x+w, 0);
bg.drawLine(x, 1, x+w-1, 1);
bg.drawLine(x, 0, x, th-1);
bg.drawLine(x+1, 0, x+1, th-2);
bg.setColor(Util.dark_edge);
bg.drawLine(x, th-1, x+w, th-1);
bg.drawLine(x, th-2, x+w-1, th-2);
bg.drawLine(x+w, th-1, x+w, 0);
bg.drawLine(x+w-1, th-1, x+w-1, 1);
int tw = fnm.stringWidth(title[i]);
if (tw < w-6)
bg.drawString(title[i], x+(w-tw)/2, th-fd-2);
// Sorting arrow
int as = th-8;
if (sortcol == i && sortdir == 1) {
bg.setColor(Util.light_edge);
bg.drawLine(x+4, th-5, x+4+as, th-5);
bg.drawLine(x+4+as, th-5, x+4+as/2, th-5-as);
bg.setColor(Util.dark_edge);
bg.drawLine(x+4+as/2, th-5-as, x+4, th-5);
}
else if (sortcol == i && sortdir == 2) {
bg.setColor(Util.light_edge);
bg.drawLine(x+4+as/2, th-5, x+4+as, th-5-as);
bg.setColor(Util.dark_edge);
bg.drawLine(x+4, th-5-as, x+4+as, th-5-as);
bg.drawLine(x+4, th-5-as, x+4+as/2, th-5);
}
// Column items
if (drawlines) {
bg.setColor(Util.body);
bg.drawLine(x+w-1, th, x+w-1, height);
bg.setColor(Util.dark_edge);
bg.drawLine(x+w, th, x+w, height);
}
for(int j=top; j<=bot; j++) {
Object o = list[i].elementAt(j);
if (o instanceof String) {
// Render string in column
String s = (String)o;
while(fnm.stringWidth(s) > w-3)
s = s.substring(0, s.length()-1);
if (!enabled)
bg.setColor(Util.body);
else if (colors != null)
bg.setColor(colors[j][i]);
bg.drawString(s, x+1, th+(j+1-top)*rowh-fd);
}
else if (o instanceof Image) {
// Render image in column
Image im = (Image)o;
bg.drawImage(im, x+1, th+(j-top)*rowh, this);
}
}
}
}
// mouseDown
// Select a list item or a column to drag
public boolean mouseDown(Event e, int x, int y)
{
if (!enabled) {
return true;
}
x -= in.left;
y -= in.top;
coldrag = -1;
if (y < th) {
// Click in title bar
for(int i=0; i<title.length; i++) {
if (adjustable && i > 0 && Math.abs(cpos[i] - x) < 3) {
// clicked on a column separator
coldrag = i;
}
else if (x >= cpos[i] && x < cpos[i+1]) {
// clicked in a title
callback.headingClicked(this, i);
}
}
}
else {
// Item chosen from list
int row = (y-th)/rowh + top;
if (row < list[0].size()) {
// Double-click?
boolean dclick = false;
if (e.when-last < 1000 && sel == row)
dclick = true;
else
last = e.when;
if (e.shiftDown() && multiselect && sel != -1) {
// Select all from last selection to this one
int zero = sels[0];
if (zero < row) {
sels = new int[row-zero+1];
for(int i=zero; i<=row; i++)
sels[i-zero] = i;
}
else {
sels = new int[zero-row+1];
for(int i=zero; i>=row; i--)
sels[zero-i] = i;
}
}
else if (e.controlDown() && multiselect) {
// Add this one to selection
int nsels[] = new int[sels.length + 1];
System.arraycopy(sels, 0, nsels, 0,sels.length);
nsels[sels.length] = row;
sels = nsels;
}
else {
// Select one row only, and de-select others
sels = new int[1];
sels[0] = row;
}
sel = row;
repaint();
last_event = e;
if (callback != null) {
// Callback the right function
if (dclick) callback.doubleClick(this, row);
else callback.singleClick(this, row);
}
else {
// Send an event
getParent().postEvent(
new Event(this,
Event.ACTION_EVENT,
dclick?"Double":"Single"));
}
}
}
return true;
}
// mouseDrag
// If a column is selected, change it's width
public boolean mouseDrag(Event e, int x, int y)
{
if (!enabled) {
return true;
}
x -= in.left;
y -= in.top;
if (coldrag != -1) {
if (x > cpos[coldrag-1]+3 && x < cpos[coldrag+1]-3) {
cpos[coldrag] = x;
cwidth[coldrag-1] = (cpos[coldrag]-cpos[coldrag-1]) /
(float)width;
cwidth[coldrag] = (cpos[coldrag+1]-cpos[coldrag]) /
(float)width;
repaint();
}
}
return true;
}
public void moved(CbScrollbar s, int v)
{
moving(s, v);
}
public void moving(CbScrollbar s, int v)
{
top = sb.getValue();
compscroll();
repaint();
}
// compscroll
// Re-compute the size of the scrollbar
private void compscroll()
{
if (fnm == null)
return; // not visible
int r = rows();
int c = list[0].size() - r;
sb.setValues(top, r==0?1:r, list[0].size());
}
// rows
// Returns the number of rows visible in the list
private int rows()
{
return Math.min(height/rowh - 1, list[0].size());
}
public Dimension minimumSize()
{
return new Dimension(400, 100);
}
public Dimension preferredSize()
{
return minimumSize();
}
}
// MultiColumnCallback
// Objects implementing this interface can be passed to the MultiColumn
// class, to have their singleClick() and doubleClick() functions called in
// response to single or double click in the list.
interface MultiColumnCallback
{
// singleClick
// Called on a single click on a list item
void singleClick(MultiColumn list, int num);
// doubleClick
// Called upon double-clicking on a list item
void doubleClick(MultiColumn list, int num);
// headingClicked
// Called when a column heading is clicked on
void headingClicked(MultiColumn list, int col);
}

578
file/MultiColumn.java.bak Normal file
View File

@ -0,0 +1,578 @@
// MultiColumn
// A List box that supports multiple columns.
import java.awt.*;
import java.util.Vector;
public class MultiColumn extends BorderPanel implements CbScrollbarCallback
{
MultiColumnCallback callback; // what to call back to
String title[]; // column titles
boolean adjustable = true;
boolean drawlines = true;
Color colors[][] = null;
boolean enabled = true;
boolean multiselect = false;
int cpos[]; // column x positions
float cwidth[]; // proportional column widths
Vector list[]; // columns of the list
CbScrollbar sb; // scrollbar at the right side
int width, height; // size, minus the scrollbar
Insets in; // used space around the border
int sbwidth; // width of the scrollbar
int th; // height of title bar
Image bim; // backing image
Graphics bg; // backing graphics
Font font = new Font("timesRoman", Font.PLAIN, 12);
FontMetrics fnm; // drawing font size
int coldrag = -1; // column being resized
int sel = -1; // selected row
int sels[] = new int[0]; // all selected rows
int top = 0; // first row displayed
long last; // last mouse click time
int rowh = 16; // row height
Event last_event; // last event that triggered callback
int sortcol; // Column currently being sorted
int sortdir; // Sort direction (0=none, 1=up, 2=down)
// Create a new list with the given column titles
MultiColumn(String t[])
{
super(3, new Color(50,50,50), new Color(220,220,220));
title = new String[t.length];
for(int i=0; i<t.length; i++)
title[i] = t[i];
list = new Vector[t.length];
for(int i=0; i<t.length; i++)
list[i] = new Vector();
cwidth = new float[t.length];
for(int i=0; i<t.length; i++)
cwidth[i] = 1.0f/t.length;
cpos = new int[t.length+1];
setLayout(null);
sb = new CbScrollbar(CbScrollbar.VERTICAL, this);
add(sb);
}
// Create a new list that calls back to the given object on
// single or double clicks.
MultiColumn(String t[], MultiColumnCallback c)
{
this(t);
callback = c;
}
// addItem
// Add a row to the list
void addItem(Object item[])
{
for(int i=0; i<title.length; i++)
list[i].addElement(item[i]);
repaint();
compscroll();
}
// addItems
// Add several rows to the list
void addItems(Object item[][])
{
for(int i=0; i<item.length; i++)
for(int j=0; j<title.length; j++)
list[j].addElement(item[i][j]);
repaint();
compscroll();
}
// modifyItem
// Changes one row of the table
void modifyItem(Object item[], int row)
{
for(int i=0; i<title.length; i++)
list[i].setElementAt(item[i], row);
repaint();
compscroll();
}
// getItem
// Returns the contents of a given row
Object []getItem(int n)
{
Object r[] = new Object[title.length];
for(int i=0; i<title.length; i++)
r[i] = list[i].elementAt(n);
return r;
}
// selected
// Return the most recently selected row
int selected()
{
return sel;
}
// select
// Select some row
void select(int s)
{
sel = s;
sels = new int[1];
sels[0] = s;
repaint();
}
// select
// Select multiple rows
void select(int s[])
{
if (s.length == 0) {
sel = -1;
sels = new int[0];
}
else {
sel = s[0];
sels = s;
}
repaint();
}
// allSelected
// Returns all the selected rows
int[] allSelected()
{
return sels;
}
// scrollto
// Scroll to make some row visible
void scrollto(int s)
{
int r = rows();
if (s < top || s >= top+r) {
top = s-1;
if (top > list[0].size() - r)
top = list[0].size() - r;
sb.setValue(top);
repaint();
}
}
// deleteItem
// Remove one row from the list
void deleteItem(int n)
{
for(int i=0; i<title.length; i++)
list[i].removeElementAt(n);
if (n == sel) {
// De-select deleted file
sel = -1;
}
for(int i=0; i<sels.length; i++) {
if (sels[i] == n) {
// Remove from selection list
int nsels[] = new int[sels.length-1];
if (nsels.length > 0) {
System.arraycopy(sels, 0, nsels, 0, i);
System.arraycopy(sels, i+1, nsels, i,
nsels.length-i);
sel = nsels[0];
}
break;
}
}
repaint();
compscroll();
}
// clear
// Remove everything from the list
void clear()
{
for(int i=0; i<title.length; i++)
list[i].removeAllElements();
sel = -1;
sels = new int[0];
top = 0;
repaint();
sb.setValues(0, 1, 0);
}
// setWidths
// Set the proportional widths of each column
void setWidths(float w[])
{
for(int i=0; i<title.length; i++)
cwidth[i] = w[i];
respace();
repaint();
}
/**Turns on or off the user's ability to adjust column widths
* @param a Can adjust or not?
*/
void setAdjustable(boolean a)
{
adjustable = a;
}
/**Turns on or off the drawing of column lines
* @param d Draw lines or not?
*/
void setDrawLines(boolean d)
{
drawlines = d;
}
/**Sets the array of colors used to draw text items.
* @param c The color array (in row/column order), or null to
* use the default
*/
void setColors(Color c[][])
{
colors = c;
repaint();
}
// Turns on or off multi-row selection with ctrl and shift
void setMultiSelect(boolean m)
{
multiselect = m;
}
// Enables the entire list
public void enable()
{
enabled = true;
sb.enable();
repaint();
}
// Disables the entire list
public void disable()
{
enabled = false;
sb.disable();
repaint();
}
// Sets or turns off the sort indication arrow for a column
// Direction 0 = None, 1 = Up arrow, 2 = Down arrow
public void sortingArrow(int col, int dir)
{
sortcol = col;
sortdir = dir;
repaint();
}
// reshape
// Called when this component gets resized
public void reshape(int nx, int ny, int nw, int nh)
{
if (nw != width+sbwidth || nh != height) {
in = insets();
sbwidth = sb.minimumSize().width;
width = nw-sbwidth - (in.left + in.right);
height = nh - (in.top + in.bottom);
sb.reshape(width+in.left, in.top, sbwidth, height);
respace();
// Force creation of a new backing image and re-painting
bim = null;
repaint();
compscroll();
}
super.reshape(nx, ny, nw, nh);
}
// respace
// Compute pixel column widths from proportional widths
void respace()
{
cpos[0] = 0;
for(int i=0; i<title.length; i++)
cpos[i+1] = cpos[i] + (int)(width*cwidth[i]);
}
// paint
// Blit the backing image to the front
public void paint(Graphics g)
{
super.paint(g);
if (bim == null) {
// This is the first rendering
bim = createImage(width, height);
bg = bim.getGraphics();
bg.setFont(font);
fnm = bg.getFontMetrics();
th = fnm.getHeight() + 4;
render();
compscroll();
}
g.drawImage(bim, in.left, in.top, this);
}
// update
// Called sometime after repaint()
public void update(Graphics g)
{
if (fnm != null) {
render();
paint(g);
}
}
// render
// Re-draw the list into the backing image
void render()
{
int fh = fnm.getHeight(), // useful font metrics
fd = fnm.getDescent(),
fa = fnm.getAscent();
int bot = Math.min(top+rows()-1, list[0].size()-1);
// Clear title section and list
bg.setColor(Color.lightGray);
bg.fillRect(0, 0, width, th);
bg.setColor(Color.white);
bg.fillRect(0, th, width, height-th);
Color lighterGray = new Color(Color.lightGray.getRed() + 20,
Color.lightGray.getGreen() + 20,
Color.lightGray.getBlue() + 20);
if (enabled) {
// Mark the selected rows
for(int i=0; i<sels.length; i++) {
if (sels[i] >= top && sels[i] <= bot) {
bg.setColor(sels[i] == sel ? Color.lightGray
: lighterGray);
bg.fillRect(0, th+(sels[i]-top)*rowh,
width, rowh);
}
}
}
// Draw each column
for(int i=0; i<title.length; i++) {
int x = cpos[i], w = cpos[i+1]-x-1;
// Column title
bg.setColor(Color.white);
bg.drawLine(x, 0, x+w, 0);
bg.drawLine(x, 1, x+w-1, 1);
bg.drawLine(x, 0, x, th-1);
bg.drawLine(x+1, 0, x+1, th-2);
bg.setColor(Color.black);
bg.drawLine(x, th-1, x+w, th-1);
bg.drawLine(x, th-2, x+w-1, th-2);
bg.drawLine(x+w, th-1, x+w, 0);
bg.drawLine(x+w-1, th-1, x+w-1, 1);
int tw = fnm.stringWidth(title[i]);
if (tw < w-6)
bg.drawString(title[i], x+(w-tw)/2, th-fd-2);
// Sorting arrow
int as = th-8;
if (sortcol == i && sortdir == 1) {
bg.setColor(Color.white);
bg.drawLine(x+4, th-5, x+4+as, th-5);
bg.drawLine(x+4+as, th-5, x+4+as/2, th-5-as);
bg.setColor(Color.black);
bg.drawLine(x+4+as/2, th-5-as, x+4, th-5);
}
else if (sortcol == i && sortdir == 2) {
bg.setColor(Color.white);
bg.drawLine(x+4+as/2, th-5, x+4+as, th-5-as);
bg.setColor(Color.black);
bg.drawLine(x+4, th-5-as, x+4+as, th-5-as);
bg.drawLine(x+4, th-5-as, x+4+as/2, th-5);
}
// Column items
if (drawlines) {
bg.setColor(Color.lightGray);
bg.drawLine(x+w-1, th, x+w-1, height);
bg.setColor(Color.black);
bg.drawLine(x+w, th, x+w, height);
}
for(int j=top; j<=bot; j++) {
Object o = list[i].elementAt(j);
if (o instanceof String) {
// Render string in column
String s = (String)o;
while(fnm.stringWidth(s) > w-3)
s = s.substring(0, s.length()-1);
if (!enabled)
bg.setColor(Color.lightGray);
else if (colors != null)
bg.setColor(colors[j][i]);
bg.drawString(s, x+1, th+(j+1-top)*rowh-fd);
}
else if (o instanceof Image) {
// Render image in column
Image im = (Image)o;
bg.drawImage(im, x+1, th+(j-top)*rowh, this);
}
}
}
}
// mouseDown
// Select a list item or a column to drag
public boolean mouseDown(Event e, int x, int y)
{
if (!enabled) {
return true;
}
x -= in.left;
y -= in.top;
coldrag = -1;
if (y < th) {
// Click in title bar
for(int i=0; i<title.length; i++) {
if (adjustable && i > 0 && Math.abs(cpos[i] - x) < 3) {
// clicked on a column separator
coldrag = i;
}
else if (x >= cpos[i] && x < cpos[i+1]) {
// clicked in a title
callback.headingClicked(this, i);
}
}
}
else {
// Item chosen from list
int row = (y-th)/rowh + top;
if (row < list[0].size()) {
// Double-click?
boolean dclick = false;
if (e.when-last < 1000 && sel == row)
dclick = true;
else
last = e.when;
if (e.shiftDown() && multiselect && sel != -1) {
// Select all from last selection to this one
int zero = sels[0];
if (zero < row) {
sels = new int[row-zero+1];
for(int i=zero; i<=row; i++)
sels[i-zero] = i;
}
else {
sels = new int[zero-row+1];
for(int i=zero; i>=row; i--)
sels[zero-i] = i;
}
}
else if (e.controlDown() && multiselect) {
// Add this one to selection
int nsels[] = new int[sels.length + 1];
System.arraycopy(sels, 0, nsels, 0,sels.length);
nsels[sels.length] = row;
sels = nsels;
}
else {
// Select one row only, and de-select others
sels = new int[1];
sels[0] = row;
}
sel = row;
repaint();
last_event = e;
if (callback != null) {
// Callback the right function
if (dclick) callback.doubleClick(this, row);
else callback.singleClick(this, row);
}
else {
// Send an event
getParent().postEvent(
new Event(this,
Event.ACTION_EVENT,
dclick?"Double":"Single"));
}
}
}
return true;
}
// mouseDrag
// If a column is selected, change it's width
public boolean mouseDrag(Event e, int x, int y)
{
if (!enabled) {
return true;
}
x -= in.left;
y -= in.top;
if (coldrag != -1) {
if (x > cpos[coldrag-1]+3 && x < cpos[coldrag+1]-3) {
cpos[coldrag] = x;
cwidth[coldrag-1] = (cpos[coldrag]-cpos[coldrag-1]) /
(float)width;
cwidth[coldrag] = (cpos[coldrag+1]-cpos[coldrag]) /
(float)width;
repaint();
}
}
return true;
}
public void moved(CbScrollbar s, int v)
{
moving(s, v);
}
public void moving(CbScrollbar s, int v)
{
top = sb.getValue();
compscroll();
repaint();
}
// compscroll
// Re-compute the size of the scrollbar
private void compscroll()
{
if (fnm == null)
return; // not visible
int r = rows();
int c = list[0].size() - r;
sb.setValues(top, r==0?1:r, list[0].size());
}
// rows
// Returns the number of rows visible in the list
private int rows()
{
return Math.min(height/rowh - 1, list[0].size());
}
public Dimension minimumSize()
{
return new Dimension(400, 100);
}
public Dimension preferredSize()
{
return minimumSize();
}
}
// MultiColumnCallback
// Objects implementing this interface can be passed to the MultiColumn
// class, to have their singleClick() and doubleClick() functions called in
// response to single or double click in the list.
interface MultiColumnCallback
{
// singleClick
// Called on a single click on a list item
void singleClick(MultiColumn list, int num);
// doubleClick
// Called upon double-clicking on a list item
void doubleClick(MultiColumn list, int num);
// headingClicked
// Called when a column heading is clicked on
void headingClicked(MultiColumn list, int col);
}

77
file/QuickSort.java Normal file
View File

@ -0,0 +1,77 @@
public class QuickSort
{
static int col, dir;
// Sorts entire array
public static void sort(RemoteFile array[], int c, int d)
{
col = c;
dir = d;
psort(array, 0, array.length - 1);
}
// Sorts partial array
public static void psort(RemoteFile array[], int start, int end)
{
int p;
if (end > start)
{
p = partition(array, start, end);
psort(array, start, p-1);
psort(array, p+1, end);
}
}
protected static int compare(RemoteFile a, RemoteFile b) {
long rv = 0;
if (col == 1)
rv = a.name.compareTo(b.name);
else if (col == 2)
rv = a.size - b.size;
else if (col == 3)
rv = a.user.compareTo(b.user);
else if (col == 4)
rv = a.group.compareTo(b.group);
else
rv = a.modified - b.modified;
rv = rv < 0 ? -1 : rv > 0 ? 1 : 0;
return (int)(dir == 2 ? -rv : rv);
}
protected static int partition(RemoteFile array[], int start, int end)
{
int left, right;
RemoteFile partitionElement;
// Arbitrary partition start...there are better ways...
partitionElement = array[end];
left = start - 1;
right = end;
for (;;)
{
while (compare(partitionElement, array[++left]) == 1)
{
if (left == end) break;
}
while (compare(partitionElement, array[--right]) == -1)
{
if (right == start) break;
}
if (left >= right) break;
swap(array, left, right);
}
swap(array, left, end);
return left;
}
protected static void swap(RemoteFile array[], int i, int j)
{
RemoteFile temp;
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}

169
file/ResizePanel.java Normal file
View File

@ -0,0 +1,169 @@
// ResizePanel
// A panel with two parts, arranged either vertically or horizontally,
// whose midpoint is adjustable
import java.awt.*;
import java.util.Vector;
public class ResizePanel extends Panel implements LayoutManager
{
Component one, two;
int pos = -1;
double ratio;
boolean vertical;
boolean dragging;
int border = 100;
// Provide two components where component one initially occupies rt fraction of
// parent area. When vertical=true components are layed out one above the other
public ResizePanel(Component one, Component two, double rt, boolean vertical)
{
this.one = one;
this.two = two;
this.vertical = vertical;
ratio = rt;
setLayout(this);
add(one);
add(two);
}
public void paint(Graphics g)
{
Dimension s = size();
if (vertical)
{
// Draw horizontal bar between vertically aligned components
pos = (int)(s.height * ratio);
g.setColor(Color.white);
g.drawLine(0, pos-2, 0, pos+1);
g.drawLine(0, pos-2, s.width-2, pos-2);
g.setColor(Color.black);
g.drawLine(s.width-1, pos+2, s.width-1, pos-1);
g.drawLine(s.width-1, pos+2, 1, pos+2);
}
else
{
// Draw vertical divider bar
pos = (int)(s.width * ratio);
g.setColor(Color.white);
g.drawLine(pos-2, 0, pos+1, 0);
g.drawLine(pos-2, 0, pos-2, s.height-2);
g.setColor(Color.black);
g.drawLine(pos+2, s.height-1, pos-1, s.height-1);
g.drawLine(pos+2, s.height-1, pos+2, 1);
}
}
// Detect mouse click on divider bar
public boolean mouseDown(Event evt, int x, int y)
{
int sh;
Dimension s = size();
if (vertical && y >= pos-2 && y <= pos+2)
{
// Started dragging
dragging = true;
}
if (!vertical && x >= pos-2 && x <= pos+2)
{
// Started dragging
dragging = true;
}
return dragging;
}
// Move division point on mouse drag
public boolean mouseDrag(Event evt, int x, int y)
{
if (dragging)
{
Dimension s = size();
if (vertical)
{
if (y < border)
pos = border;
else if (y > s.height - border)
pos = s.height - border;
else
pos = y;
ratio = (double)pos / (double)s.height;
}
else
{
if (x < border)
pos = border;
else if (x > s.width - border)
pos = s.width - border;
else
pos = x;
ratio = (double)pos / (double)s.width;
}
layoutContainer(this);
repaint();
}
return dragging;
}
// No longer dragging on mouse button release
public boolean mouseUp(Event evt, int x, int y)
{
boolean o = dragging;
dragging = false;
return o;
}
public void addLayoutComponent(String name, Component comp)
{
}
// Arrange components within container
public void layoutContainer(Container parent)
{
Dimension s = parent.size();
if (vertical)
{
pos = (int)(s.height * ratio);
one.reshape(0, 0, s.width, pos-3);
one.layout();
two.reshape(0, pos+3, s.width, s.height - pos - 5);
two.layout();
}
else
{
pos = (int)(s.width * ratio);
one.reshape(0, 0, pos-3, s.height);
one.layout();
two.reshape(pos+3, 0, s.width - pos - 5, s.height);
two.layout();
}
}
// Determine minimum size for ResizePanel
public Dimension minimumLayoutSize(Container parent)
{
Dimension d1 = one.minimumSize(),
d2 = two.minimumSize();
if (vertical)
{
// Largest of the widths, sum of the heights
return new Dimension(d1.width > d2.width ? d1.width : d2.width,
d1.height + d2.height);
}
else
{
// Largest of the heights, sum of the widths
return new Dimension(d1.width + d2.width,
d1.height > d2.height ? d1.height : d2.height);
}
}
public Dimension preferredLayoutSize(Container parent)
{
return minimumLayoutSize(parent);
}
public void removeLayoutComponent(Component comp)
{
}
}

24
file/StaticTextField.java Normal file
View File

@ -0,0 +1,24 @@
import java.awt.*;
// StaticTextField
// A text field that is set to be non-editable by default
class StaticTextField extends TextField
{
StaticTextField()
{
super();
setEditable(false);
}
StaticTextField(String s)
{
super(s);
setEditable(false);
}
StaticTextField(String s, int i)
{
super(s,i);
setEditable(false);
}
}

103
file/StringSplitter.java Normal file
View File

@ -0,0 +1,103 @@
import java.util.Vector;
// StringSplitter
// A stringsplitter object splits a string into a number of substrings,
// each separated by one separator character. Separator characters can be
// included in the string by escaping them with a \
public class StringSplitter
{
Vector parts = new Vector();
int pos = 0;
StringSplitter(String str, char sep)
{
this(str, sep, true);
}
StringSplitter(String str, char sep, boolean escape)
{
StringBuffer current;
parts.addElement(current = new StringBuffer());
for(int i=0; i<str.length(); i++) {
char c = str.charAt(i);
if (c == '\\' && i != str.length()-1 && escape)
current.append(str.charAt(++i));
else if (c == sep)
parts.addElement(current = new StringBuffer());
else
current.append(c);
}
}
// countTokens
// The number of tokens left in the string
int countTokens()
{
return parts.size() - pos;
}
// hasMoreTokens
// Can we call nextToken?
boolean hasMoreTokens()
{
return pos < parts.size();
}
// nextToken
// Returns the string value of the next token
String nextToken()
{
if (pos < parts.size())
return ((StringBuffer)parts.elementAt(pos++)).toString();
else
return null;
}
// gettokens
// Returns a vector of strings split from the given input string
Vector gettokens()
{
return parts;
}
}
// StringJoiner
// The complement of StringSplitter. Takes a number of substrings and adds
// them to a string, separated by some character. If the separator character
// appears in one of the substrings, escape it with a \
class StringJoiner
{
char sep;
StringBuffer str = new StringBuffer();
int count = 0;
// Create a new StringJoiner using the given separator
StringJoiner(char s)
{
sep = s;
}
// add
// Add one string, and a separator
void add(String s)
{
if (count != 0)
str.append(sep);
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c == sep || c == '\\') str.append('\\');
str.append(c);
}
count++;
}
// toString
// Get the resulting string
public String toString()
{
return str.toString();
}
}

185
file/TabbedPanel.java Normal file
View File

@ -0,0 +1,185 @@
// TabbedPanel
// A panel capable of displaying one of many components at a time. The
// component to display is chosen by a row of tab buttons.
import java.awt.*;
import java.util.Vector;
public class TabbedPanel extends Panel
{
TabSelector tab; // component for choosing panel
TabbedDisplayPanel disp; // where other panels are displayed
CardLayout card;
TabbedPanel()
{
this(Util.body_hi, Util.dark_edge_hi, Util.body);
}
TabbedPanel(Color hi, Color lo, Color bk)
{
setLayout(new BorderLayout());
add("North",tab = new TabSelector(hi, lo, bk));
add("Center",disp = new TabbedDisplayPanel(hi, lo));
disp.setLayout(card = new CardLayout());
}
// addItem
// Add a component to be chosen by a tab with the given name
void addItem(String n, Component c)
{
tab.addItem(n);
disp.addItem(n, c);
}
// select
// Display a component in the panel
void select(String n)
{
tab.choose(n);
disp.choose(n);
}
// chose
// Called back by a TabSelector object when the user clicks on a tab
void chose(String n)
{
disp.choose(n);
}
}
class TabSelector extends Canvas
{
Color hi, lo, bk;
Vector name = new Vector();
int chosen = 0;
Font font = new Font("timesRoman", Font.PLAIN, 12),
chfont = new Font(font.getName(), Font.BOLD, 13);
TabSelector(Color h, Color l, Color b)
{
hi = h; lo = l; bk = b;
}
void addItem(String n)
{
name.addElement(n);
paint(getGraphics());
}
void choose(String n)
{
for(int i=0; i<name.size(); i++)
if (((String)name.elementAt(i)).equals(n)) {
chosen = i;
paint(getGraphics());
}
}
public void paint(Graphics g)
{
if (g == null || name.size() == 0)
return;
g.setColor(bk);
g.fillRect(0, 0, size().width, size().height);
int tw = size().width / name.size(),
th = size().height;
for(int i=0; i<name.size(); i++) {
int x = tw*i;
if (i == chosen) {
g.setColor(lo);
g.drawLine(x+tw-3, 1, x+tw-3, th-1);
g.drawLine(x+tw-4, 2, x+tw-4, th-1);
g.setColor(hi);
g.drawLine(x, 0, x, th-1);
g.drawLine(x+1, 0, x+1, th-1);
g.drawLine(x, 0, x+tw-4, 0);
g.drawLine(x, 1, x+tw-5, 1);
g.drawLine(x+tw-3, th-1, x+tw-1, th-1);
g.drawLine(x+tw-3, th-2, x+tw-1, th-2);
}
else {
g.setColor(lo);
g.drawLine(x+tw-3, 6, x+tw-3, th-1);
g.drawLine(x+tw-4, 7, x+tw-4, th-1);
g.setColor(hi);
g.drawLine(x, 5, x, th-1);
g.drawLine(x+1, 5, x+1, th-1);
g.drawLine(x, 5, x+tw-4, 5);
g.drawLine(x, 6, x+tw-5, 6);
g.drawLine(x, th-1, x+tw-1, th-1);
g.drawLine(x, th-2, x+tw-1, th-2);
}
g.setColor(lo);
if (i == chosen) g.setFont(chfont);
else g.setFont(font);
String str = (String)name.elementAt(i);
int textw = g.getFontMetrics().stringWidth(str);
int texth = g.getFontMetrics().getHeight();
if (textw < tw-5)
g.drawString(str, x+(tw-textw)/2, (th-texth)/2+texth);
}
}
public boolean mouseDown(Event evt, int x, int y)
{
if (name.size() == 0) return false;
chosen = x / (size().width / name.size());
paint(getGraphics());
((TabbedPanel)getParent()).chose((String)name.elementAt(chosen));
return true;
}
public Dimension minimumSize()
{
return new Dimension(50,25);
}
public Dimension preferredSize()
{
return minimumSize();
}
}
class TabbedDisplayPanel extends Panel
{
Color hi, lo;
CardLayout card;
TabbedDisplayPanel(Color h, Color l)
{
hi = h; lo = l;
setLayout(card = new CardLayout());
}
// addItem
// Add one component to the set of possibles to be shown
void addItem(String n, Component c)
{
add(n, c);
}
// choose
// Display the named panel
void choose(String n)
{
((CardLayout)getLayout()).show(this, n);
}
public Insets insets()
{
return new Insets(5,5,5,5);
}
public void paint(Graphics g)
{
g.setColor(hi);
g.drawLine(0, 0, 0, size().height-1);
g.drawLine(1, 0, 1, size().height-1);
g.setColor(lo);
g.drawLine(0, size().height-1, size().width-1, size().height-1);
g.drawLine(0, size().height-2, size().width-1, size().height-2);
g.drawLine(size().width-1, size().height-1, size().width-1, 0);
g.drawLine(size().width-2, size().height-1, size().width-2, 0);
}
}

333
file/ToolbarLayout.java Normal file
View File

@ -0,0 +1,333 @@
import java.awt.*;
import java.lang.Math;
/**
* A ToolbarLayout arranges components in a left-to-right flow, much
* like the FlowLayout which is supplied with the JDK. However, it
* fixes the problem with the FlowLayout that occurs when a FlowLayout
* is for a North aligned component of a BorderLayout--namely, that
* if the window is shrunk so that some of the components within the
* FlowLayout wrap to the next line the component does not grow in
* height to support this wrapping. This bug was caused by the library
* designers using the preferred size in recalculating, not the size
* which is determined by the window width. As such, the flow layout
* would always want to be the height of one row.
*
* A ToolbarLayout lets each component assume its natural (preferred) size.
*
* NOTE: This class was initially a subclass of FlowLayout, but we
* encountered problems using that approach.
*
* @version 0.10, 1999-04-27
* @author Peter Armstrong
* @author Tony Johnson
*/
public class ToolbarLayout implements LayoutManager, java.io.Serializable {
/**
* This value indicates that each row of components
* should be left-justified.
*/
public static final int LEFT = 0;
/**
* This value indicates that each row of components
* should be centered.
*/
public static final int CENTER = 1;
/**
* This value indicates that each row of components
* should be right-justified.
*/
public static final int RIGHT = 2;
int align;
int hgap;
int vgap;
/**
* Constructs a new ToolbarLayout with a left alignment and a
* default 5-unit horizontal and vertical gap.
*/
public ToolbarLayout() {
this(LEFT, 5, 5);
}
/**
* Constructs a new ToolbarLayout with the specified alignment and a
* default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* <code>ToolbarLayout.LEFT</code>, <code>ToolbarLayout.RIGHT</code>,
* or <code>ToolbarLayout.CENTER</code>.
* @param align the alignment value
*/
public ToolbarLayout(int align) {
this(align, 5, 5);
}
/**
* Creates a new ToolbarLayout with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>ToolbarLayout.LEFT</code>, <code>ToolbarLayout.RIGHT</code>,
* or <code>ToolbarLayout.CENTER</code>.
* @param align the alignment value.
* @param hgap the horizontal gap between components.
* @param vgap the vertical gap between components.
*/
public ToolbarLayout(int align, int hgap, int vgap) {
this.align = align;
this.hgap = hgap;
this.vgap = vgap;
}
/**
* Gets the alignment for this layout.
* Possible values are <code>ToolbarLayout.LEFT</code>,
* <code>ToolbarLayout.RIGHT</code>, or <code>ToolbarLayout.CENTER</code>.
* @return the alignment value for this layout.
* @see ToolbarLayout#setAlignment
*/
public int getAlignment() {
return align;
}
/**
* Sets the alignment for this layout.
* Possible values are <code>ToolbarLayout.LEFT</code>,
* <code>ToolbarLayout.RIGHT</code>, and <code>ToolbarLayout.CENTER</code>.
* @param align the alignment value.
* @see ToolbarLayout#getAlignment
*/
public void setAlignment(int align) {
this.align = align;
}
/**
* Gets the horizontal gap between components.
* @return the horizontal gap between components.
* @see ToolbarLayout#setHgap
*/
public int getHgap() {
return hgap;
}
/**
* Sets the horizontal gap between components.
* @param hgap the horizontal gap between components
* @see ToolbarLayout#getHgap
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
/**
* Gets the vertical gap between components.
* @return the vertical gap between components.
* @see ToolbarLayout#setVgap
*/
public int getVgap() {
return vgap;
}
/**
* Sets the vertical gap between components.
* @param vgap the vertical gap between components
* @see ToolbarLayout#getVgap
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
/**
* Adds the specified component to the layout. Sets the orientation to be horizontal.
* @param name the name of the component
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
}
/**
* Removes the specified component from the layout. Not used by
* this class.
* @param comp the component to remove
* @see java.awt.Container#removeAll
*/
public void removeLayoutComponent(Component comp) {
}
/**
* Returns the preferred dimensions for this layout given the components
* in the specified target container. This method is the difference
* between ToolbarLayout and FlowLayout.
* @param target the component which needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container.
* @see Container
* @see #minimumLayoutSize
* @see java.awt.Container#getPreferredSize
*/
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
Insets insets = target.getInsets();
int numRows = 1; //the number of rows
int rowSumWidth = insets.left + insets.right; //the width of the row so far
int rowMaxWidth = target.getSize().width; //the width that the ToolbarLayout is in
int rowHeight = 0; //the height of each row
int numOnRow = 0; //the number of components on the row
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
rowHeight = Math.max(rowHeight, d.height); //make each row the height of the biggest component of all
if (i > 0) {
rowSumWidth += hgap;//add on the pre-spacing if this is not the first component
}
rowSumWidth += d.width; //add the width of the component
//if it overflowed and if there are components already on this row then bump this component to next row
if ((rowSumWidth + hgap) > rowMaxWidth) {
if (numOnRow > 0) {
numRows++;
rowSumWidth = insets.left + insets.right + d.width;
numOnRow = 0;//reset the number of components on the next row (we ++ no matter what later)
}
}
numOnRow++;//add this component to the count of the number on the row
}
}
dim.width = rowMaxWidth;
dim.height = insets.top + insets.bottom + numRows*rowHeight + vgap*(numRows + 1);
return dim;
}
}
/**
* Returns the minimum dimensions needed to layout the components
* contained in the specified target container.
* @param target the component which needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container.
* @see #preferredLayoutSize
* @see java.awt.Container
* @see java.awt.Container#doLayout
*/
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getMinimumSize();
dim.height = Math.max(dim.height, d.height);
if (i > 0) {
dim.width += hgap;
}
dim.width += d.width;
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
/**
* Centers the elements in the specified row, if there is any slack.
* @param target the component which needs to be moved
* @param x the x coordinate
* @param y the y coordinate
* @param width the width dimensions
* @param height the height dimensions
* @param rowStart the beginning of the row
* @param rowEnd the the ending of the row
*/
private void moveComponents(Container target, int x, int y, int width, int height, int rowStart, int rowEnd) {
synchronized (target.getTreeLock()) {
switch (align) {
case LEFT:
break;
case CENTER:
x += width / 2;
break;
case RIGHT:
x += width;
break;
}
for (int i = rowStart ; i < rowEnd ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
m.setLocation(x, y + (height - m.size().height) / 2);
x += hgap + m.size().width;
}
}
}
}
/**
* Lays out the container. This method lets each component take
* its preferred size by reshaping the components in the
* target container in order to satisfy the constraints of
* this <code>ToolbarLayout</code> object.
* @param target the specified component being laid out.
* @see Container
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
int maxwidth = target.size().width - (insets.left + insets.right + hgap*2);
int nmembers = target.getComponentCount();
int x = 0, y = insets.top + vgap;
int rowh = 0, start = 0;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
if ((x == 0) || ((x + d.width) <= maxwidth)) {
if (x > 0) {
x += hgap;
}
x += d.width;
rowh = Math.max(rowh, d.height);
} else {
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, i);
x = d.width;
y += vgap + rowh;
rowh = d.height;
start = i;
}
}
}
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, nmembers);
}
}
/**
* Returns a string representation of this <code>ToolbarLayout</code>
* object and its values.
* @return a string representation of this layout.
*/
public String toString() {
String str = "";
switch (align) {
case LEFT: str = ",align=left"; break;
case CENTER: str = ",align=center"; break;
case RIGHT: str = ",align=right"; break;
}
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
}
}

148
file/Util.java Normal file
View File

@ -0,0 +1,148 @@
import java.awt.*;
import java.awt.image.*;
class Util
{
static Frame fr;
static Graphics g;
static Font f;
static FontMetrics fnm;
static Toolkit tk;
static Color light_edge = Color.white;
static Color dark_edge = Color.black;
static Color body = Color.lightGray;
static Color body_hi = new Color(210, 210, 210);
static Color light_edge_hi = Color.white;
static Color dark_edge_hi = Color.darkGray;
static Color dark_bg = new Color(150, 150, 150);
static Color text = Color.black;
static Color light_bg = Color.white;
static
{
fr = new Frame();
fr.addNotify();
g = fr.getGraphics();
setFont(new Font("TimesRoman", Font.PLAIN, 8));
tk = Toolkit.getDefaultToolkit();
}
static boolean waitForImage(Image i)
{
MediaTracker mt = new MediaTracker(fr);
mt.addImage(i, 0);
try { mt.waitForAll(); } catch(Exception e) { return false; }
return !mt.isErrorAny();
}
static boolean waitForImage(Image i, int w, int h)
{
MediaTracker mt = new MediaTracker(fr);
mt.addImage(i, w, h, 0);
try { mt.waitForAll(); } catch(Exception e) { return false; }
return !mt.isErrorAny();
}
static int getWidth(Image i)
{
waitForImage(i);
return i.getWidth(fr);
}
static int getHeight(Image i)
{
waitForImage(i);
return i.getHeight(fr);
}
static Image createImage(int w, int h)
{
return fr.createImage(w, h);
}
static Image createImage(ImageProducer p)
{
return fr.createImage(p);
}
static Object createObject(String name)
{
try {
Class c = Class.forName(name);
return c.newInstance();
}
catch(Exception e) {
System.err.println("Failed to create object "+name+" : "+
e.getClass().getName());
System.exit(1);
}
return null;
}
/**Create a new instance of some object
*/
static Object createObject(Object o)
{
try { return o.getClass().newInstance(); }
catch(Exception e) {
System.err.println("Failed to reproduce object "+o+" : "+
e.getClass().getName());
System.exit(1);
}
return null;
}
static void dottedRect(Graphics g, int x1, int y1,
int x2, int y2, int s)
{
int i, s2 = s*2, t;
if (x2 < x1) { t = x1; x1 = x2; x2 = t; }
if (y2 < y1) { t = y1; y1 = y2; y2 = t; }
for(i=x1; i<=x2; i+=s2)
g.drawLine(i, y1, i+s > x2 ? x2 : i+s, y1);
for(i=y1; i<=y2; i+=s2)
g.drawLine(x2, i, x2, i+s > y2 ? y2 : i+s);
for(i=x2; i>=x1; i-=s2)
g.drawLine(i, y2, i-s < x1 ? x1 : i-s, y2);
for(i=y2; i>=y1; i-=s2)
g.drawLine(x1, i, x1, i-s < y1 ? y1 : i-s);
}
static void recursiveLayout(Container c)
{
c.layout();
for(int i=0; i<c.countComponents(); i++) {
Component cc = c.getComponent(i);
if (cc instanceof Container)
recursiveLayout((Container)cc);
}
}
static void recursiveBackground(Component c, Color b)
{
if (c instanceof TextField || c instanceof Choice ||
c instanceof TextArea)
return; // leave these alone
c.setBackground(b);
if (c instanceof Container) {
Container cn = (Container)c;
for(int i=0; i<cn.countComponents(); i++)
recursiveBackground(cn.getComponent(i), b);
}
}
static void recursiveBody(Component c)
{
recursiveBackground(c, Util.body);
}
static void setFont(Font nf)
{
f = nf;
g.setFont(f);
fnm = g.getFontMetrics();
}
}

143
file/acl_security.pl Normal file
View File

@ -0,0 +1,143 @@
require 'file-lib.pl';
do '../ui-lib.pl';
# acl_security_form(&options)
# Output HTML for editing security options for the file module
sub acl_security_form
{
print "<tr> <td><b>$text{'acl_user'}</b></td>\n";
local $u = $_[0]->{'uid'} < 0 ? '' : getpwuid($_[0]->{'uid'});
printf "<td colspan=3><input type=radio name=uid_def value=1 %s> %s\n",
$_[0]->{'uid'} < 0 ? 'checked' : '', $text{'acl_user_def'};
printf "<input type=radio name=uid_def value=0 %s>\n",
$_[0]->{'uid'} < 0 ? '' : 'checked';
print "<input name=uid size=8 value='$u'> ",
&user_chooser_button("uid", 0),"</td> </tr>\n";
print "<tr> <td><b>$text{'acl_umask'}</b></td>\n";
print "<td colspan=3><input name=umask size=3 value='$_[0]->{'umask'}'></td> </tr>\n";
print "<tr> <td><b>$text{'acl_follow'}</b></td> <td colspan=3>\n";
printf "<input type=radio name=follow value=1 %s> $text{'yes'}\n",
$_[0]->{'follow'} == 1 ? "checked" : "";
printf "<input type=radio name=follow value=2 %s> $text{'acl_fyes'}\n",
$_[0]->{'follow'} == 2 ? "checked" : "";
printf "<input type=radio name=follow value=0 %s> $text{'no'}</td> </tr>\n",
$_[0]->{'follow'} == 0 ? "checked" : "";
print "<tr> <td><b>$text{'acl_ro'}</b></td> <td colspan=3>\n";
printf "<input type=radio name=ro value=1 %s> $text{'yes'}\n",
$_[0]->{'ro'} ? "checked" : "";
printf "<input type=radio name=ro value=0 %s> $text{'no'}</td> </tr>\n",
$_[0]->{'ro'} ? "" : "checked";
print "<tr> <td><b>$text{'acl_max'}</b></td>\n";
printf "<td colspan=3><input type=radio name=max_def value=1 %s> %s\n",
$_[0]->{'max'} ? "" : "checked", $text{'acl_unlim'};
printf "<input type=radio name=max_def value=0 %s>\n",
$_[0]->{'max'} ? "checked" : "";
printf "<input name=max size=8 value='%s'> %s</td> </tr>\n",
$_[0]->{'max'}, $text{'acl_b'};
print "<tr> <td><b>$text{'acl_archive'}</b></td> <td colspan=3>\n";
printf "<input type=radio name=archive value=1 %s> $text{'yes'}\n",
$_[0]->{'archive'} == 1 ? "checked" : "";
printf "<input type=radio name=archive value=2 %s> $text{'acl_archmax'}\n",
$_[0]->{'archive'} == 2 ? "checked" : "";
printf "<input name=archmax size=10 value='%s'> %s\n",
$_[0]->{'archmax'}, $text{'acl_b'};
printf "<input type=radio name=archive value=0 %s> $text{'no'}</td> </tr>\n",
$_[0]->{'archive'} == 0 ? "checked" : "";
print "<tr> <td><b>$text{'acl_unarchive'}</b></td> <td colspan=3>\n";
printf "<input type=radio name=unarchive value=2 %s> %s\n",
$_[0]->{'unarchive'} == 2 ? "checked" : "", $text{'acl_unarchive2'};
printf "<input type=radio name=unarchive value=1 %s> %s\n",
$_[0]->{'unarchive'} == 1 ? "checked" : "", $text{'acl_unarchive1'};
printf "<input type=radio name=unarchive value=0 %s> %s</td> </tr>\n",
$_[0]->{'unarchive'} == 0 ? "checked" : "", $text{'acl_unarchive0'};
print "<tr> <td><b>$text{'acl_dostounix'}</b></td> <td colspan=3>\n";
printf "<input type=radio name=dostounix value=1 %s> %s\n",
$_[0]->{'dostounix'} == 1 ? "checked" : "", $text{'yes'};
printf "<input type=radio name=dostounix value=0 %s> %s</td> </tr>\n",
$_[0]->{'dostounix'} == 0 ? "checked" : "", $text{'no'};
print "<tr> <td valign=top><b>$text{'acl_buttons'}</b></td> <td colspan=3>\n";
foreach $b (@file_buttons) {
printf "<input type=checkbox name=button_%s %s> %s<br>\n",
$b, $_[0]->{'button_'.$b} ? "checked" : "",
$text{'acl_button_'.$b};
}
print "</td> </tr>\n";
print "<tr> <td><b>$text{'acl_noperms'}</b></td>\n";
print "<td>",&ui_radio("noperms", int($_[0]->{'noperms'}),
[ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]),"</td>\n";
print "<td><b>$text{'acl_nousers'}</b></td>\n";
print "<td>",&ui_radio("nousers", int($_[0]->{'nousers'}),
[ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]),"</td> </tr>\n";
print "<tr> <td><b>$text{'acl_filesystems'}</b></td>\n";
print "<td>",&ui_yesno_radio("filesystems",
int($_[0]->{'filesystems'})),"</td>\n";
print "<td><b>$text{'acl_contents'}</b></td>\n";
print "<td>",&ui_yesno_radio("contents",
int($_[0]->{'contents'})),"</td> </tr>\n";
print "<tr> <td><b>$text{'acl_chroot'}</b></td>\n";
printf "<td colspan=3><input name=chroot size=40 value='%s'></td>\n",
$_[0]->{'chroot'};
print "<tr> <td valign=top><b>$text{'acl_dirs'}</b><br>$text{'acl_relto'}</td>\n";
print "<td colspan=3><textarea name=root rows=3 cols=40>",
join("\n", split(/\s+/, $_[0]->{'root'})),"</textarea><br>\n";
printf "<input type=checkbox name=home value=1 %s> %s<br>\n",
$_[0]->{'home'} ? 'checked' : '', $text{'acl_home'};
printf "<input type=checkbox name=goto value=1 %s> %s</td>\n",
$_[0]->{'goto'} ? 'checked' : '', $text{'acl_goto'};
print "<tr> <td valign=top><b>$text{'acl_nodirs'}</b><br>$text{'acl_relto'}</td>\n";
print "<td colspan=3><textarea name=noroot rows=3 cols=40>",
join("\n", split(/\s+/, $_[0]->{'noroot'})),"</textarea><br>\n";
}
# acl_security_save(&options)
# Parse the form for security options for the file module
sub acl_security_save
{
$_[0]->{'uid'} = $in{'uid_def'} ? -1 : getpwnam($in{'uid'});
$in{'root'} =~ s/\r//g;
local @root = split(/\s+/, $in{'root'});
map { s/\/+/\//g } @root;
map { s/([^\/])\/+$/$1/ } @root;
$_[0]->{'root'} = join(" ", @root);
$in{'noroot'} =~ s/\r//g;
local @noroot = split(/\s+/, $in{'noroot'});
map { s/\/+/\//g } @noroot;
map { s/([^\/])\/+$/$1/ } @noroot;
$_[0]->{'noroot'} = join(" ", @noroot);
$_[0]->{'follow'} = $in{'follow'};
$_[0]->{'ro'} = $in{'ro'};
$in{'umask'} =~ /^[0-7]{3}$/ || &error("Invalid umask");
$_[0]->{'umask'} = $in{'umask'};
$_[0]->{'home'} = $in{'home'};
$_[0]->{'goto'} = $in{'goto'};
$_[0]->{'max'} = $in{'max_def'} ? undef : $in{'max'};
$_[0]->{'archive'} = $in{'archive'};
$_[0]->{'archmax'} = $in{'archmax'};
foreach $b (@file_buttons) {
$_[0]->{"button_$b"} = $in{"button_$b"};
}
$_[0]->{'unarchive'} = $in{'unarchive'};
$_[0]->{'dostounix'} = $in{'dostounix'};
$_[0]->{'chroot'} = $in{'chroot'};
$_[0]->{'noperms'} = $in{'noperms'};
$_[0]->{'nousers'} = $in{'nousers'};
$_[0]->{'filesystems'} = $in{'filesystems'};
$_[0]->{'contents'} = $in{'contents'};
}

92
file/chmod.cgi Executable file
View File

@ -0,0 +1,92 @@
#!/usr/local/bin/perl
# chmod.cgi
# Change the ownership and permissions on a file
require './file-lib.pl';
$disallowed_buttons{'info'} && &error($text{'ebutton'});
&ReadParse();
&webmin_log($in{'linkto'} ? "relink" : "chmod", undef, $in{'path'}, \%in);
&switch_acl_uid_and_chroot();
print "Content-type: text/plain\n\n";
!$access{'ro'} && &can_access($in{'path'}) ||
&failure(&text('chmod_eaccess', $in{'path'}));
if (defined($in{'user'})) {
$uid = $in{'user'} =~ /^\d+$/ ? $in{'user'} :
defined(%user_to_uid) ? $user_to_uid{$in{'user'}} :
getpwnam($in{'user'});
&failure(&text('chmod_euser', $in{'user'})) if (!defined($uid));
$gid = $in{'group'} =~ /^\d+$/ ? $in{'group'} :
defined(%group_to_gid) ? $group_to_gid{$in{'group'}} :
getgrnam($in{'group'});
&failure(&text('chmod_egroup', $in{'group'})) if (!defined($gid));
}
if ($in{'linkto'}) {
# Just changing the link target
$follow && &failure($text{'chmod_efollow'});
&lock_file($in{'path'});
unlink($in{'path'});
symlink($in{'linkto'}, $in{'path'}) ||
&failure(&text('chmod_elink', $1));
&unlock_file($in{'path'});
}
elsif ($in{'rec'} == 0) {
# Just this file
&update($in{'path'}, 0);
}
elsif ($in{'rec'} == 1) {
# This directory and all its files
&update($in{'path'}, 0);
opendir(DIR, $in{'path'});
foreach $f (readdir(DIR)) {
next if ($f eq "." || $f eq "..");
next if (-l $full);
&update("$in{'path'}/$f", 1) if (!-d $full);
}
closedir(DIR);
}
elsif ($in{'rec'} == 2) {
# Directory and all subdirectories
&update($in{'path'}, 0);
&recurse($in{'path'});
}
print "\n";
sub recurse
{
local(@files, $f, $full);
opendir(DIR, $_[0]);
@files = readdir(DIR);
closedir(DIR);
foreach $f (@files) {
$full = "$_[0]/$f";
next if ($f eq "." || $f eq "..");
next if (-l $full);
&update($full, !-d $full);
&recurse($full) if (-d $full);
}
}
sub failure
{
print @_,"\n";
exit;
}
# update(file, perms_only)
sub update
{
local $perms = $in{'perms'};
if (defined($perms)) {
if ($_[1]) {
@st = stat($_[0]);
$perms = ($perms & 0777) | ($st[2] & 037777777000);
}
chmod($perms, $_[0]) || &failure(&text('chmod_echmod', $!));
}
if (defined($uid)) {
chown($uid, $gid, $_[0]) || &failure(&text('chmod_echown', $!));
}
}

5
file/config Normal file
View File

@ -0,0 +1,5 @@
hide_dot_files=0
iconsize=0
nocharset=0
extract=1
force_text=0

16
file/config-*-linux Normal file
View File

@ -0,0 +1,16 @@
xfs_acl=&has_command("getfacl") && &has_command("setfacl")
ext2_acl=&has_command("getfacl") && &has_command("setfacl")
ext3_acl=&has_command("getfacl") && &has_command("setfacl")
reiserfs_acl=&has_command("getfacl") && &has_command("setfacl")
xfs_attr=&has_command("attr")
ext2_attr=&has_command("attr")
ext3_attr=&has_command("attr")
ext2_ext=&has_command("lsattr") && &has_command("chattr")
ext3_ext=&has_command("lsattr") && &has_command("chattr")
getfacl=getfacl
setfacl=setfacl --set-file=-
hide_dot_files=0
iconsize=0
nocharset=0
extract=1
force_text=0

9
file/config-irix Normal file
View File

@ -0,0 +1,9 @@
xfs_acl=&has_command("chacl")
xfs_attr=&has_command("attr")
getfacl=./irix-getfacl.pl
setfacl=./irix-setfacl.pl
hide_dot_files=0
iconsize=0
nocharset=0
extract=1
force_text=0

10
file/config-solaris Normal file
View File

@ -0,0 +1,10 @@
ufs_acl=&has_command("getfacl") && &has_command("setfacl")
nfs_acl=&has_command("getfacl") && &has_command("setfacl")
lofs_acl=&has_command("getfacl") && &has_command("setfacl")
getfacl=getfacl
setfacl=setfacl -f -
hide_dot_files=0
iconsize=0
nocharset=0
extract=1
force_text=0

8
file/config.info Normal file
View File

@ -0,0 +1,8 @@
hide_dot_files=Show files starting with a dot?,1,0-Yes,1-No
iconsize=Size of buttons in toolbar,1,1-Small,0-Large with labels
nocharset=Attempt to use proper character set?,1,0-Yes,1-No
extract=Extract .class files from JAR?,1,1-Yes,0-No
width=Width for scaled images,3,Default (300 pixels)
fixed=Font size for text,3,Default (12 points)
small_fixed=Font size for buttons,3,Default (10 points)
force_text=Editor for HTML files,1,1-Text editor,0-HTML editor

8
file/config.info.ca Executable file
View File

@ -0,0 +1,8 @@
hide_dot_files=Mostra els fitxers que comencen amb un punt,1,0-S<>,1-No
iconsize=Mida dels botons a la barra d'eines,1,1-Petita,0-Gran amb etiquetes
nocharset=Intenta fer servir el joc de car<61>cters apropiat,1,0-S<>,1-No
extract=Extreu els fitxers .class del JAR?,1,1-S<>,0-No
width=Amplada de les imatges escalades,3,Per defecte (300 p<>xels)
fixed=Mida de la tipografia del text,3,Per defecte (12 punts)
small_fixed=Mida de la tipografia dels botons,3,Per defecte (10 punts)
force_text=Editor de fitxers HTML,1,1-Editor de text,0-Editor HTML

4
file/config.info.de Normal file
View File

@ -0,0 +1,4 @@
hide_dot_files=Zeige Dateien mit einem Punkt am Anfang?,1,0-Ja,1-Nein
iconsize=Gr&#246;&#223;e der Buttons in der Toolbar,1,1-Klein,0-Gro&#223; mit Bildunterschrift
nocharset=Versuche passende Zeichens&#228;tze zu benutzen?,1,0-Ja,1-Nein
extract=.class&#45;Dateien aus dem JAR extrahieren?,1,1-Ja,0-Nein

4
file/config.info.es Normal file
View File

@ -0,0 +1,4 @@
hide_dot_files=&#191;Mostrar archivos que comienzan con punto?,1,0-S&#237;,1-No
iconsize=Tama&#241;o de botones en la barra de herramientas,1,1-Peque&#241;o,0-Grande con etiquetas
nocharset=&#191;Intentar usar el juego de caracteres apropiado?,1,0-S&#237;,1-No
extract=&#191;Extraer archivos .class del JAR?,1,1-S&#237;,0-No

6
file/config.info.fa Normal file
View File

@ -0,0 +1,6 @@

hide_dot_files=آيا پرونده‌هايي که با يک نقطه آغاز مي‌شوند نمايش داده شوند؟,1,0-بله,1-خير
iconsize=اندازه دگمه‌ها در نوار ابزار,1,1-کوچک,0-بزرگ به همراه برچسبها
nocharset=آيا مي‌خواهيد از مجموعه کاراکترهاي خاص استفاده کنيد؟,1,0-بله,1-خير
extract=آيا پرونده‌هاي .class از پرونده‌هاي JAR استخراج شوند؟,1,1-بله,0-خير

4
file/config.info.it Executable file
View File

@ -0,0 +1,4 @@
hide_dot_files=Visualizza i file che iniziano con un punto?,1,0-Si,1-No
iconsize=Dimensioni dei pulsanti nella barra degli strumenti,1,1-Piccoli,0-Grandi con etichette
nocharset=Tenta di usare il set di caratteri appropriato?,1,0-Si,1-No
extract=Estrarre i file .class dall'archivio JAR?,1,1-Si,0-No

4
file/config.info.tr Normal file
View File

@ -0,0 +1,4 @@
hide_dot_files=Nokta ile ba<62>layan dosyalar g<>sterilsin mi?,1,0-Evet,1-Hay<61>r
iconsize=Ara<72> <20>ubu<62>undaki butonlar<61>n boyutu,1,1-K<><4B><EFBFBD>k,0-Geni<6E> ve etiketli
nocharset=Uygun karakter seti kullan<61>lmaya <20>al<61><6C><EFBFBD>ls<6C>n m<>?,1,0-Evet,1-Hay<61>r
extract=JAR'daki .class dosyalar<61> a<><61>ls<6C>n m<>?,1,1-Evet,0-Hay<61>r

49
file/copy.cgi Executable file
View File

@ -0,0 +1,49 @@
#!/usr/local/bin/perl
# copy.cgi
# Copy some file or directory
require './file-lib.pl';
$disallowed_buttons{'copy'} && &error($text{'ebutton'});
&ReadParse();
&webmin_log("copy", undef, $in{'from'}, \%in);
print "Content-type: text/plain\n\n";
if ($access{'ro'} || !&can_access($in{'from'})) {
print &text('copy_efrom', $in{'from'}),"\n";
exit;
}
if (!&can_access($in{'to'})) {
print &text('copy_eto', $in{'to'}),"\n";
exit;
}
if (-l &unmake_chroot($in{'from'})) {
# Remake the link
&switch_acl_uid_and_chroot();
&lock_file($in{'to'});
if (!symlink(readlink($in{'from'}), $in{'to'})) {
print &text('copy_elink', $!),"\n";
exit;
}
&unlock_file($in{'to'});
$err = undef;
$info = $in{'to'};
}
else {
&switch_acl_uid();
($ok, $err) = &copy_source_dest(&unmake_chroot($in{'from'}), &unmake_chroot($in{'to'}));
$err = undef if ($ok);
$info = &unmake_chroot($in{'to'});
}
if ($err) {
print $err,"\n";
}
else {
print "\n";
print &file_info_line($info),"\n";
}
sub split_dir
{
$_[0] =~ /^(.*\/)([^\/]+)$/;
return ($1, $2);
}

33
file/defaultacl Normal file
View File

@ -0,0 +1,33 @@
noconfig=0
user=0
root=/
follow=0
umask=022
log=0
ro=0
goto=1
archive=1
button_save=1
button_edit=1
button_info=1
button_acl=1
button_attr=1
button_ext=1
button_search=1
button_delete=1
button_new=1
button_upload=1
button_mkdir=1
button_makelink=1
button_rename=1
button_sharing=1
button_mount=1
button_copy=1
button_preview=1
unarchive=1
dostounix=1
chroot=/
noperms=0
nousers=0
filesystems=1
contents=1

26
file/delete.cgi Executable file
View File

@ -0,0 +1,26 @@
#!/usr/local/bin/perl
# delete.cgi
# Delete some file or directory
require './file-lib.pl';
$disallowed_buttons{'delete'} && &error($text{'ebutton'});
&ReadParse();
&webmin_log("delete", undef, $in{'file'}, \%in);
print "Content-type: text/plain\n\n";
if ($access{'ro'} || !&can_access($in{'file'})) {
print &text('delete_eaccess', $in{'file'}),"\n";
exit;
}
if (-r &unmake_chroot($in{'file'}) && !-d &unmake_chroot($in{'file'})) {
&switch_acl_uid_and_chroot();
$rv = unlink($in{'file'});
if (!$rv) { print "$!\n"; }
else { print "\n"; }
}
else {
&switch_acl_uid();
($ok, $err) = &unlink_file(&unmake_chroot($in{'file'}));
if (!$ok) { print "$err\n"; }
else { print "\n"; }
}

54
file/edit_html.cgi Executable file
View File

@ -0,0 +1,54 @@
#!/usr/local/bin/perl
# Show an HTML editor window
require './file-lib.pl';
do '../ui-lib.pl';
$disallowed_buttons{'edit'} && &error($text{'ebutton'});
&ReadParse();
&popup_header($in{'file'} ? $text{'html_title'} : $text{'html_title2'},
undef, "onload='initEditor()'");
# Output HTMLarea init code
print <<EOF;
<script type="text/javascript">
_editor_url = "$gconfig{'webprefix'}/$module_name/xinha/";
_editor_lang = "en";
</script>
<script type="text/javascript" src="xinha/htmlarea.js"></script>
<script type="text/javascript">
var editor = null;
function initEditor() {
editor = new HTMLArea("body");
editor.generate();
return false;
}
</script>
EOF
# Read the file
&switch_acl_uid_and_chroot();
$data = &read_file_contents($in{'file'});
# Output text area
print &ui_form_start("save_html.cgi", "form-data");
if ($in{'file'}) {
# Editing existing file
print &ui_hidden("file", $in{'file'}),"\n";
$pc = 95;
}
else {
# Creating new, so prompt for path
print $text{'edit_filename'}," ",
&ui_textbox("file", $in{'dir'}, 70),"<br>\n";
$pc = 90;
}
print "<textarea rows=20 cols=80 style='width:100%;height:$pc%' name=body id=body>";
print &html_escape($data);
print "</textarea>\n";
print &ui_submit($text{'html_save'});
print &ui_form_end();
&popup_footer();

21
file/extract.cgi Executable file
View File

@ -0,0 +1,21 @@
#!/usr/local/bin/perl
# Extract a zip, tar, tar.gz or tar.bz file on the server
require './file-lib.pl';
&ReadParse();
print "Content-type: text/plain\n\n";
# Check permissions
$disallowed_buttons{'upload'} && &error($text{'ebutton'});
if (!&can_access($in{'file'})) {
print &text('extract_eperm', $in{'file'}),"\n";
exit(0);
}
# Go for it
&webmin_log("extract", undef, $in{'file'});
$realfile = &unmake_chroot($in{'file'});
&switch_acl_uid();
$err = &extract_archive($in{'file'}, $in{'delete'});
print $err,"\n";

452
file/file-lib.pl Normal file
View File

@ -0,0 +1,452 @@
# file-lib.pl
# Common functions for file manager CGIs
do '../web-lib.pl';
&ReadParse(\%prein, 'GET');
if ($prein{'trust'}) {
&open_trust_db();
if ($trustdb{$prein{'trust'}}) {
$trust_unknown_referers = 1;
$trustdb{$prein{'trust'}} = time();
}
dbmclose(%trustdb);
}
&init_config();
do '../ui-lib.pl';
@file_buttons = ( "save", "preview", "edit", "info", "acl", "attr", "ext", "search",
"delete", "new", "upload", "mkdir", "makelink",
"rename", "sharing", "mount", "copy" );
if ($module_info{'usermin'}) {
# Usermin gets the allowed list from the module config
&switch_to_remote_user();
&create_user_config_dirs();
$hide_dot_files = $userconfig{'hide_dot_files'};
$follow = int($config{'follow'});
$real_home_dir = &simplify_path(&resolve_links($remote_user_info[7]));
$upload_max = $config{'max'};
if ($config{'home_only'} == 1) {
@allowed_roots = ( $real_home_dir,
split(/\s+/, $config{'root'}) );
}
elsif ($config{'home_only'} == 2) {
@allowed_roots = split(/\s+/, $config{'root'});
}
else {
@allowed_roots = ( "/" );
}
@denied_roots = split(/\s+/, $config{'noroot'});
if ($config{'archive'} eq 'y') {
$archive = 1;
}
elsif ($config{'archive'} eq 'n') {
$archive = 0;
}
else {
$archive = 2;
$archmax = $config{'archive'};
}
$unarchive = 1;
$dostounix = 1;
$chroot = "/";
@disallowed_buttons = ( );
foreach $k (keys %config) {
if ($k =~ /^button_(.*)/ && $config{$k} == 0) {
push(@disallowed_buttons, $1);
}
}
$canperms = 1;
$canusers = 1;
$contents = 1;
}
else {
# Webmin gets the list of allowed directories from the ACL
%access = &get_module_acl();
$hide_dot_files = $config{'hide_dot_files'};
$follow = int($access{'follow'});
$upload_max = $access{'max'};
@allowed_roots = split(/\s+/, $access{'root'});
if ($access{'home'}) {
local @u = getpwnam($remote_user);
if (@u) {
push(@allowed_roots,
&simplify_path(&resolve_links($u[7])));
}
}
@denied_roots = split(/\s+/, $access{'noroot'});
$archive = $access{'archive'};
$archmax = $access{'archmax'};
$unarchive = $access{'unarchive'};
$dostounix = $access{'dostounix'};
$chroot = $access{'chroot'};
$access{'button_search'} = 0 if (!&has_command("find"));
$access{'button_makelink'} = 0 if (!&supports_symlinks());
$access{'button_info'} = 0 if (!&supports_users());
@disallowed_buttons = grep { !$access{'button_'.$_} } @file_buttons;
if (&is_readonly_mode()) {
# Force read-only mode for file manager if global readonly
# is in effect.
$access{'ro'} = 1;
}
$canperms = $access{'noperms'} ? 0 : 1;
$canusers = $access{'nousers'} ? 0 : 1;
$contents = $access{'contents'};
}
%disallowed_buttons = map { $_, 1 } @disallowed_buttons;
$icon_map = ( "c", 1, "txt", 1,
"pl", 1, "cgi", 1,
"html", 1, "htm", 1,
"gif", 2, "jpg", 2,
"tar", 3
);
# file_info_line(path, [displaypath])
# Returns a line of text containing encoded details of some file
sub file_info_line
{
local @st;
local $islink = (-l $_[0]);
local $f = $islink && &must_follow($_[0]);
local @st = $f ? stat($_[0]) : lstat($_[0]);
local $ext = $_[0] =~ /\S+\.([^\.\/]+)$/ ? $1 : undef;
local $dp = $_[1] || $_[0];
$dp =~ s/\\/\\\\/g;
$dp =~ s/\t/\\t/g;
return undef if ($dp =~ /\r|\n/);
if (!@st) {
# Work around a broken stat function on large files on redhat 7.x
&has_command("stat") || return undef;
local $out = `stat -t '$_[0]'`;
return undef if ($?);
$out =~ /^(.*)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
local $type = defined($icon_map{$ext}) ? $icon_map{$ext} : 4;
local $user = defined(%uid_to_user) ? $uid_to_user{$5} : getpwuid($5);
$user = $5 if (!$user);
local $group = defined(%gid_to_group) ? $gid_to_group{$6} :getgrgid($6);
$group = $6 if (!$group);
local $size = $2;
local $mtime = $13;
local $mode = hex($4);
return sprintf ("%s\t%u\t%s\t%s\t%u\t%u\t%u\t%s",
$dp, $type, $user, $group, $size, $mode, $mtime, undef);
}
local $type = $islink && !$f ? 5 :
-d _ ? 0 :
-b _ ? 6 :
-c _ ? 6 :
-p _ ? 7 :
-S _ ? 7 : defined($icon_map{$ext}) ? $icon_map{$ext} : 4;
local $user = !&supports_users() ? "root" :
defined(%uid_to_user) ? $uid_to_user{$st[4]} : getpwuid($st[4]);
$user = $st[4] if (!$user);
local $group = !&supports_users() ? "root" :
defined(%gid_to_group) ? $gid_to_group{$st[5]} :getgrgid($st[5]);
$group = $st[5] if (!$group);
local $rl = readlink($_[0]);
return join("\t", $dp, $type,
$user, $group,
$st[7] < 0 ? 2**32+$st[7] : $st[7], $st[2],
$st[9], $f ? "" : $islink && !$rl ? "???" : $rl);
}
# switch_acl_uid()
sub switch_acl_uid
{
if (!$module_info{'usermin'} && $access{'uid'}) {
local @u = $access{'uid'} < 0 ? getpwnam($remote_user)
: getpwuid($access{'uid'});
@u || &error($text{'switch_euser'});
$( = $u[3]; $) = "$u[3] ".join(" ", $u[3], &other_groups($u[0]));
($>, $<) = ($u[2], $u[2]);
umask(oct($access{'umask'}));
}
}
# switch_acl_uid_and_chroot()
# Combines the switch_acl_uid and go_chroot functions
sub switch_acl_uid_and_chroot
{
if (!$module_info{'usermin'} && $access{'uid'}) {
local @u = $access{'uid'} < 0 ? getpwnam($remote_user)
: getpwuid($access{'uid'});
@u || &error($text{'switch_euser'});
local @other = &other_groups($u[0]);
&go_chroot();
$( = $u[3]; $) = "$u[3] ".join(" ", $u[3], @other);
($>, $<) = ($u[2], $u[2]);
umask(oct($access{'umask'}));
}
else {
&go_chroot();
}
}
# can_access(file)
# Returns 1 if some file can be edited/deleted
sub can_access
{
return &under_root_dir($_[0], \@allowed_roots) &&
($_[0] eq "/" || !&under_root_dir($_[0], \@denied_roots));
}
# under_root_dir(file, &roots)
# Returns 1 if some file is under one of the given roots
sub under_root_dir
{
local @f = grep { $_ ne '' } split(/\//, $_[0]);
local $r;
DIR: foreach $r (@{$_[1]}) {
return 1 if ($r eq '/' || $_[0] eq '/' || $_[0] eq $r);
local @a = grep { $_ ne '' } split(/\//, $r);
local $i;
for($i=0; $i<@a; $i++) {
next DIR if ($a[$i] ne $f[$i]);
}
return 1;
}
return 0;
}
# can_list(dir)
# Returns 1 if some directory can be listed. Parent directories of allowed
# directories are included as well.
sub can_list
{
return &under_root_dir_or_parent($_[0], \@allowed_roots) &&
($_[0] eq "/" || !&under_root_dir($_[0], \@denied_roots));
}
# under_root_dir_or_parent(file, &roots)
# Returns 1 if some file is under one of the given roots, or their parents
sub under_root_dir_or_parent
{
local @f = grep { $_ ne '' } split(/\//, $_[0]);
DIR: foreach $r (@allowed_roots) {
return 1 if ($r eq '/' || $_[0] eq '/' || $_[0] eq $r);
local @a = grep { $_ ne '' } split(/\//, $r);
local $i;
for($i=0; $i<@a && $i<@f; $i++) {
next DIR if ($a[$i] ne $f[$i]);
}
return 1;
}
return 0;
}
# accessible_subdir(dir)
# Returns the path to a dir under the given one that we can access
sub accessible_subdir
{
local ($r, @rv);
foreach $r (@allowed_roots) {
if ($r =~ /^(\Q$_[0]\E\/[^\/]+)/) {
push(@rv, $1);
}
}
return @rv;
}
sub open_trust_db
{
local $trust = "$ENV{'WEBMIN_CONFIG'}/file/trust";
eval "use SDBM_File";
dbmopen(%trustdb, $trust, 0700);
eval { $trustdb{'1111111111'} = 'foo bar' };
if ($@) {
dbmclose(%trustdb);
eval "use NDBM_File";
dbmopen(%trustdb, $trust, 0700);
}
}
# must_follow(path)
# For symlinks, returns 1 if a link should be follow, 0 if not
sub must_follow
{
if ($follow == 1) {
return 1;
}
elsif ($follow == 0) {
return 0;
}
else {
local @s = stat($_[0]);
local @l = lstat($_[0]);
@st = ($s[4] == $l[4] ? @s : @l);
return $s[4] == $l[4];
}
}
# extract_archive(path, delete)
# Called by upload to extract some zip or tar.gz file. Returns undef if something
# was actually done, an error message otherwise.
sub extract_archive
{
local $out;
$_[0] =~ /^(\S*\/)/ || return 0;
local $dir = $1;
local $qdir = quotemeta($dir);
local $qpath = quotemeta($_[0]);
if ($_[0] =~ /\.zip$/i) {
# Extract zip file
return &text('zip_ecmd', "unzip") if (!&has_command("unzip"));
$out = `(cd $qdir; unzip -o $qpath) 2>&1 </dev/null`;
if ($?) {
return &text('zip_eunzip', $out);
}
}
elsif ($_[0] =~ /\.tar$/i) {
# Extract un-compressed tar file
return &text('zip_ecmd', "tar") if (!&has_command("tar"));
$out = `(cd $qdir; tar xf $qpath) 2>&1 </dev/null`;
if ($?) {
return &text('zip_euntar', $out);
}
}
elsif ($_[0] =~ /\.(tar\.gz|tgz|tar\.bz|tbz|tar\.bz2|tbz2)$/i) {
# Extract gzip or bzip2-compressed tar file
local $zipper = $_[0] =~ /bz(2?)$/i ? "bunzip2"
: "gunzip";
return &text('zip_ecmd', "tar") if (!&has_command("tar"));
return &text('zip_ecmd', $zipper) if (!&has_command($zipper));
$out = `(cd $qdir; $zipper -c $qpath | tar xf -) 2>&1`;
if ($?) {
return &text('zip_euntar2', $out);
}
}
elsif ($_[0] =~ /\.gz$/i) {
# Uncompress gzipped file
return &text('zip_ecmd', "gunzip") if (!&has_command("gunzip"));
local $final = $_[0];
$final =~ s/\.gz$//;
local $qfinal = quotemeta($final);
$out = `(cd $qdir; gunzip -c $qpath >$qfinal) 2>&1`;
if ($?) {
return &text('zip_euntar2', $out);
}
}
else {
return $text{'zip_ename'};
}
if ($_[1]) {
unlink($_[0]);
}
return undef;
}
# post_upload(path, dir, unzip)
sub post_upload
{
local ($path, $dir, $zip) = @_;
if ($unarchive == 2) {
$zip = $path =~ /\.(zip|tgz|tar|tar\.gz)$/i ? 1 : 0;
}
elsif ($unarchive == 0) {
$zip = 0;
}
local $refresh = $path;
local $err;
if ($zip) {
$err = &extract_archive($path, $zip-1);
if (!$err) {
# Refresh whole dir
$refresh = $in{'dir'};
}
}
$info = &file_info_line(&unmake_chroot($refresh), $refresh);
print "<script>\n";
print "opener.document.FileManager.",
"upload_notify(\"$refresh\", \"$info\");\n";
if ($err) {
$err =~ s/\r//g;
$err =~ s/\n/\\n/g;
print "opener.document.FileManager.","upload_error(\"",&text('zip_err', $err),"\");\n";
}
print "close();\n";
print "</script>\n";
}
sub go_chroot
{
if ($chroot ne "/" && $chroot ne "") {
# First build hash of users and groups, which will not be accessible
# after a chroot
local (@u, @g);
setpwent();
while(@u = getpwent()) {
$uid_to_user{$u[2]} = $u[0] if (!defined($uid_to_user{$u[2]}));
$user_to_uid{$u[0]} = $u[2] if (!defined($user_to_uid{$u[0]}));
}
endpwent();
setgrent();
while(@g = getgrent()) {
$gid_to_group{$g[2]} = $g[0] if(!defined($gid_to_group{$g[2]}));
$group_to_gid{$g[0]} = $g[2] if(!defined($group_to_gid{$g[0]}));
}
endgrent();
chroot($chroot) || die("chroot to $chroot failed");
}
}
# make_chroot(dir)
# Converts some real directory to the chroot form
sub make_chroot
{
if ($chroot eq "/") {
return $_[0];
}
elsif ($_[0] eq $chroot) {
return "/";
}
else {
local $rv = $_[0];
if ($rv =~ /^$chroot\//) {
$rv =~ s/^$chroot//;
return $rv;
}
else {
return undef;
}
}
}
# unmake_chroot(dir)
# Converts some chroot'd directory to the real form
sub unmake_chroot
{
if ($chroot eq "/") {
return $_[0];
}
elsif ($_[0] eq "/") {
return $chroot;
}
else {
return $chroot.$_[0];
}
}
# print_content_type()
# Prints the content-type header, with a charset
sub print_content_type
{
if ($userconfig{'nocharset'} || $config{'nocharset'}) {
# Never try to use charset
print "Content-type: text/plain\n\n";
}
else {
$charset = &get_charset();
print "Content-type: text/plain; charset=$charset\n\n";
}
}
1;

64
file/filesystems.cgi Executable file
View File

@ -0,0 +1,64 @@
#!/usr/local/bin/perl
# filesystems.cgi
# List all filesystems and their types
require './file-lib.pl';
print "Content-type: text/plain\n\n";
if (!&foreign_check("mount") || !$access{'filesystems'}) {
print "0\n";
exit;
}
&foreign_require("mount", "mount-lib.pl");
@mtab = &mount::list_mounted();
%mtab = map { $_->[0], $_ } @mtab;
@fstab = &mount::list_mounts();
%fstab = map { $_->[0], $_ } @fstab;
@mounts = ( @fstab, grep { !$fstab{$_->[0]} } @mtab );
print "1\n";
foreach $m (sort { length($a->[0]) <=> length($b->[0]) } @mounts) {
next if ($m->[0] !~ /^\//);
local @supp = @{$support{$m->[2]}};
if (!@supp) {
# Work out what this filesystem supports
@supp = ( eval $config{$m->[2]."_acl"} ? 1 : 0,
eval $config{$m->[2]."_attr"} ? 1 : 0,
eval $config{$m->[2]."_ext"} ? 1 : 0 );
$support{$m->[2]} = \@supp;
}
# Check if the filesystem really does support attrs and ACLs
local @supp2 = @supp;
if ($mtab{$m->[0]}) {
if ($supp2[0]) {
local $out = `$config{'getfacl'} '$m->[0]' 2>/dev/null`;
if ($?) {
$supp2[0] = 0;
}
else {
local $aclcount;
foreach $l (split(/\n/, $out)) {
$l =~ s/#.*$//;
$l =~ s/\s+$//;
$aclcount++ if ($l =~ /\S/);
}
$supp2[0] = 0 if (!$aclcount);
}
}
if ($supp2[1]) {
local $out = `attr -l '$m->[0]' 2>/dev/null`;
if ($?) {
$supp2[1] = 0;
}
}
}
$m->[1] =~ s/\\/\//g;
$chrooted = &make_chroot($m->[0]);
if ($chrooted) {
print join(" ", $chrooted, @$m[1..3], @supp2,
$mtab{$m->[0]} ? 1 : 0,
$fstab{$m->[0]} ? 1 : 0),"\n";
}
}

36
file/getattrs.cgi Executable file
View File

@ -0,0 +1,36 @@
#!/usr/local/bin/perl
# getattrs.cgi
# Returns a list in URL-encode name=value format of attributes on some file
require './file-lib.pl';
&ReadParse();
&switch_acl_uid_and_chroot();
print "Content-type: text/plain\n\n";
if (!&can_access($in{'file'})) {
print $text{'facl_eaccess'},"\n";
}
else {
$out = `attr -l '$in{'file'}' 2>&1`;
if ($?) {
print $out,"\n";
}
else {
foreach $l (split(/[\r\n]+/, $out)) {
if ($l =~ /Attribute\s+"(.*)"/i) {
# Get the valid for this attribute
local $name = $1;
$got = `attr -g '$name' '$in{'file'}' 2>&1`;
if ($? || $got !~ /^(.*)\n([\0-\377]*)\n$/) {
print $got,"\n";
exit;
}
push(@rv, [ $name, $2 ] );
}
}
print "\n";
foreach $r (@rv) {
print &urlize($r->[0]),"=",&urlize($r->[1]),"\n";
}
}
}

25
file/getext.cgi Executable file
View File

@ -0,0 +1,25 @@
#!/usr/local/bin/perl
# getext.cgi
# Returns a string of EXT attributes for some file
require './file-lib.pl';
&ReadParse();
&switch_acl_uid_and_chroot();
print "Content-type: text/plain\n\n";
if (!&can_access($in{'file'})) {
print $text{'facl_eaccess'},"\n";
}
else {
$out = `lsattr -d '$in{'file'}' 2>&1`;
$out =~ s/^lsattr.*\n//;
if ($? || $out !~ /^(\S+)\s/) {
print $out,"\n";
}
else {
print "\n";
@a = split(//, $1);
print join("", grep { $_ ne '-' } @a),"\n";
}
}

24
file/getext.cgi.bak Executable file
View File

@ -0,0 +1,24 @@
#!/usr/local/bin/perl
# getext.cgi
# Returns a string of EXT attributes for some file
require './file-lib.pl';
&ReadParse();
&switch_acl_uid();
print "Content-type: text/plain\n\n";
if (!&can_access($in{'file'})) {
print $text{'facl_eaccess'},"\n";
}
else {
$out = `lsattr -d '$in{'file'}' 2>&1`;
if ($? || $out !~ /^(\S+)\s/) {
print $out,"\n";
}
else {
print "\n";
@a = split(//, $1);
print join("", grep { $_ ne '-' } @a),"\n";
}
}

45
file/getfacl.cgi Executable file
View File

@ -0,0 +1,45 @@
#!/usr/local/bin/perl
# getfacl.cgi
# Gets the ACLs for some file
require './file-lib.pl';
&ReadParse();
&switch_acl_uid_and_chroot();
print "Content-type: text/plain\n\n";
if (!&can_access($in{'file'})) {
print $text{'facl_eaccess'},"\n";
}
else {
$getfacl = $config{'getfacl'};
if ($getfacl =~ /^\.\//) {
$getfacl =~ s/^\./$module_root_directory/;
}
chdir("/");
if ($in{'file'} eq '/') {
$in{'file'} = '.';
}
else {
$in{'file'} =~ s/^\///;
}
$out = `$getfacl '$in{'file'}' 2>&1`;
if ($?) {
print $out,"\n";
}
else {
foreach $l (split(/\n/, $out)) {
$l =~ s/#.*$//;
$l =~ s/\s+$//;
push(@rv, $l) if ($l =~ /\S/);
}
if (!@rv) {
print "Filesystem does not support ACLs\n";
}
else {
print "\n";
foreach $l (@rv) {
print $l,"\n";
}
}
}
}

Binary file not shown.

BIN
file/images/Thumbs.db Executable file

Binary file not shown.

BIN
file/images/acl.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

BIN
file/images/add.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

BIN
file/images/all.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

BIN
file/images/attr.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

BIN
file/images/binary.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

BIN
file/images/cancel.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

BIN
file/images/config.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

BIN
file/images/copy.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 B

BIN
file/images/cut.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

BIN
file/images/delete.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

BIN
file/images/device.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

BIN
file/images/dir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

BIN
file/images/down.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

BIN
file/images/edit.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

BIN
file/images/ext.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
file/images/extract.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
file/images/file.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
file/images/find.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

BIN
file/images/goto.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

BIN
file/images/html.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
file/images/icon.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

BIN
file/images/image.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

BIN
file/images/makelink.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

BIN
file/images/mdir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
file/images/mkdir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

BIN
file/images/mount.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

BIN
file/images/new.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

BIN
file/images/open.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

BIN
file/images/paste.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

BIN
file/images/pipe.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

BIN
file/images/preview.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

BIN
file/images/props.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

BIN
file/images/refresh.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

BIN
file/images/rename.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

BIN
file/images/replace.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

BIN
file/images/ret.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

BIN
file/images/run.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

BIN
file/images/save.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

BIN
file/images/sdir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

BIN
file/images/search.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

BIN
file/images/share.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

BIN
file/images/smallicon.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

BIN
file/images/smdir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

BIN
file/images/sub.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

BIN
file/images/sudir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

BIN
file/images/symlink.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

BIN
file/images/text.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 B

BIN
file/images/udir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Some files were not shown because too many files have changed in this diff Show More