home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 13.7 KB | 542 lines |
- // JFSclient.java
- // A connection to a jfs server, for use by JFS applets
- import java.io.*;
- import java.net.*;
- import java.util.Vector;
- import java.util.StringTokenizer;
- import CryptConnection;
- import Message;
- import BufferInputStream;
- import BufferOutputStream;
-
- public class JFSclient
- {
- String serverhost; // server we are connected to
- String authname, authpass; // name and password, or null
- CryptConnection con;
- CryptInputStream in; // data from server
- CryptOutputStream out; // data to server
- CutBuffer cb; // shared cut buffer
- String currentdir = "/", // default dir for load/save
- currentfile = "", // default filename
- currenttype = null; // last saved mime type
-
- // Create a client object and connect to the given JFS server
- JFSclient(String host) throws IOException
- {
- Socket s = new Socket(host, 9888);
- try {
- con = new CryptConnection(s.getInputStream(),
- s.getOutputStream());
- }
- catch(IOException e);
- in = con.getInputStream();
- out = con.getOutputStream();
- serverhost = host;
- cb = new CutBuffer();
- }
-
- // Create a client object with the given host, name, password and
- // cutbuffer. This only exists for calling from newclient().
- JFSclient(String host, String n, String p, CutBuffer c)
- throws IOException
- {
- this(host);
- if (n != null && p != null) {
- auth(n,p);
- authname = n;
- authpass = p;
- }
- cb = c;
- }
-
- // newclient
- // Create a new JFSclient object, with a new connection to the
- // server. If this client was authenticated, the new one will be too.
- JFSclient newclient() throws RequestException
- {
- try return new JFSclient(serverhost, authname, authpass, cb);
- catch(IOException e)
- throw new RequestException("Error reconnecting to server");
- }
-
- // setbuf & getbuf
- // Set and get the shared cut buffer selection used by this client
- void setbuf(Object o) { cb.buf = o; }
- Object getbuf() { return cb.buf; }
-
- // close
- // Disconnect from the server
- void close()
- {
- Message m = new Message();
- m.add("Request","Close");
- m.send(out);
- try {
- out.close();
- in.close();
- }
- catch(IOException e);
- }
-
- // auth
- // Send an Auth request to the server and wait for a reply.
- void auth(String name, String pass) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Auth");
- m.add("Username",name);
- m.add("Password",pass);
- m.send(out);
- Message r = getreply();
- authname = name;
- authpass = pass;
- currentdir = uinfo(authname).home;
- }
-
- // getdir
- // Returns a JFSdirectory structure containing info about the files
- // in the given directory.
- JFSdirectory getdir(String path) throws RequestException
- {
- byte dirdata[] = getsect(path, 0, -1, -1);
- BufferInputStream buf = new BufferInputStream(dirdata);
- try return new JFSdirectory(buf);
- catch(IOException e)
- throw new RequestException("Error parsing directory : "+
- e.getMessage());
- }
-
- // statfile
- // Returns the JFSfile structure for a given filename
- JFSfile statfile(String path) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Stat");
- m.add("File",path);
- m.send(out);
- Message r = getreply();
- BufferInputStream buf = new BufferInputStream(r.getdata());
- JFSdirectory tmpdir = null;
- try tmpdir = new JFSdirectory(buf);
- catch(IOException e)
- throw new RequestException("Error parsing file details");
- return (JFSfile)tmpdir.files.elementAt(0);
- }
-
- // get
- // Returns the data from the given file and version. If ver is 0,
- // then the latest version should be received.
- // At the moment, the file is requested in 8k chunks, as trying to read
- // more than that at one go hangs some java implementations (such
- // as netscape).
- byte []get(String path, int ver) throws RequestException
- {
- BufferOutputStream buf = new BufferOutputStream();
- byte sect[] = null;
- int pos = 0, chunk = 8000;
- do {
- sect = getsect(path, ver, pos, pos+chunk-1);
- buf.write(sect);
- pos += chunk;
- } while(sect.length == chunk);
- return buf.getarray();
- }
-
- // getsect
- // Returns the data from part of a given file and version, or the
- // whole file is start == -1
- byte []getsect(String path, int ver, int st, int en)
- throws RequestException
- {
- Message m = new Message();
- if (ver != 0)
- m.add("Version",String.valueOf(ver));
- if (st >= 0) {
- m.add("Start",String.valueOf(st));
- m.add("End",String.valueOf(en));
- }
- return devget(path, m).getdata();
- }
-
- // devget
- // Sends a Get request, but with the headers from the given message
- // added. Useful for reading from device drivers.
- Message devget(String file, Message head) throws RequestException
- {
- Message m = new Message();
- m.add("Request", "Get");
- m.add("File", file);
- for(int i=0; i<head.size(); i++)
- m.add(head.name(i), head.value(i));
- m.send(out);
- return getreply();
- }
-
- // put
- // Sends data to be stored under the given name, version and mime type
- void put(String path, int ver, byte data[], String type)
- throws RequestException
- {
- Message m = new Message();
- if (ver != 0)
- m.add("Version",String.valueOf(ver));
- m.add("Content-type",type);
- devput(path, data, m);
- }
-
- // devput
- // Sends a Put request, but with the headers from the given message
- // added. Useful for writing to device drivers.
- void devput(String file, byte d[], Message head) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Put");
- m.add("File", file);
- m.setdata(d);
- for(int i=0; i<head.size(); i++)
- m.add(head.name(i), head.value(i));
- m.send(out);
- getreply();
- }
-
- // gethandler
- // Returns the handler class (from the file /etc/programs) for the
- // given mime type.
- String gethandler(String typestr) throws RequestException
- {
- MimeType type = new MimeType(typestr);
- if (!type.exact())
- throw new RequestException("Mime type "+typestr+
- " contains wildcards");
- Vector pr = new Vector(), ty = new Vector();
- getprograms(pr, ty);
- for(int i=0; i<pr.size(); i++) {
- String hprog = (String)pr.elementAt(i);
- MimeType htype = (MimeType)ty.elementAt(i);
- if (htype != null && htype.equals(type))
- return hprog;
- }
- return null;
- }
-
- // getprograms
- // Fills in the p vector with the list of known programs
- // from the server, and the t vector with the mime types for those
- // programs (or null)
- void getprograms(Vector p, Vector t) throws RequestException
- {
- BufferInputStream buf = new BufferInputStream(get("/etc/programs", 0));
- while(true) {
- String line = null;
- try line = buf.gets();
- catch(IOException e)
- break;
- StringTokenizer tok = new StringTokenizer(line," \t");
- if (tok.countTokens() < 1)
- continue;
- String prog = tok.nextToken();
- MimeType type = null;
- if (tok.countTokens() > 0) {
- type = new MimeType(tok.nextToken());
- if (!type.valid())
- throw new RequestException("Bogus mime type "+
- "in /etc/programs");
- }
- p.addElement(prog);
- t.addElement(type);
- }
- }
-
- // getprinters
- // Fill the given vectors with the names, types, descriptions and
- // print commands for all printers on the server.
- void getprinters(Vector name, Vector type, Vector desc, Vector cmd)
- throws RequestException
- {
- BufferInputStream pfile = new BufferInputStream(get("/etc/printers",0));
- try {
- while(true) {
- String line = pfile.gets();
- StringSplitter tok = new StringSplitter(line,':');
- if (tok.countTokens() != 4)
- continue;
- name.addElement(tok.nextToken());
- type.addElement(tok.nextToken());
- desc.addElement(tok.nextToken());
- cmd.addElement(tok.nextToken());
- }
- }
- catch(IOException e);
- }
-
- // delete
- // Requests the deletion of the given file and version. If the version
- // is 0, all versions of this file will be deleted.
- void delete(String file, int v) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Delete");
- m.add("File",file);
- if (v != 0)
- m.add("Version",String.valueOf(v));
- m.send(out);
- getreply();
- }
-
- // mkdir
- // Send a request to create the given directory.
- void mkdir(String dir) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Mkdir");
- m.add("Directory",dir);
- m.send(out);
- getreply();
- }
-
- // copy
- // Send a request to copy one file to another
- void copy(String src, String dst) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Copy");
- m.add("Source",src);
- m.add("Destination",dst);
- m.send(out);
- getreply();
- }
-
- // uinfo
- // Returns a JFSuser structure for the given username, with the
- // password field cleared. If the username is null, then the name
- // of the current user is used.
- JFSuser uinfo(String u) throws RequestException
- {
- Message m = new Message();
- m.add("Request", "Uinfo");
- m.add("Username", u==null ? authname : u);
- m.send(out);
-
- Message r = getreply();
- byte ba[] = r.getdata();
- char ca[] = new char[ba.length];
- for(int i=0; i<ba.length; i++)
- ca[i] = (char)ba[i];
- String str = new String(ca);
- try return new JFSuser(str);
- catch(IOException e)
- throw new RequestException("User format error");
- }
-
- // ulist
- // Returns a vector of JFSuser structures for all the users on the
- // server (minus the password fields).
- Vector ulist() throws RequestException
- {
- // send request
- Message m = new Message();
- m.add("Request", "Ulist");
- m.send(out);
-
- // read and parse reply
- Message r = getreply();
- BufferInputStream buf = new BufferInputStream(r.getdata());
- Vector ul = new Vector();
- try while(true) ul.addElement(new JFSuser(buf.gets()));
- catch(IOException e);
- return ul;
- }
-
- // ginfo
- // Returns a list of users belonging to the given group
- Vector ginfo(String g) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Ginfo");
- m.add("Group",g);
- m.send(out);
-
- Message r = getreply();
- BufferInputStream buf = new BufferInputStream(r.getdata());
- Vector uv = new Vector();
- while(true) {
- try uv.addElement(buf.gets());
- catch(IOException e) break;
- }
- return uv;
- }
-
- // chmod
- // Sends a Chmod request to the server. Can be used to add, delete
- // or change the permissions of a user.
- void chmod(String f, String u, String p) throws RequestException
- {
- Message m = new Message();
- m.add("Request","Chmod");
- m.add("File",f);
- m.add("User",u);
- if (p != null) m.add("Perms",p);
- m.send(out);
- getreply();
- }
-
- // getprop
- // Get one property from the server identified by the given name
- // and user. If the user parameter is null, then the name of the
- // current user is used.
- ServerProperty getprop(String name, String user)
- {
- Message m = new Message();
- m.add("Request", "Getprop");
- m.add("Property", name);
- m.add("User", user==null ? authname : user);
- m.send(out);
-
- try return new ServerProperty(new String(getreply().getdata(),0));
- catch(Exception e)
- return null;
- }
-
- // putprop
- // Attempt to store a property on the server. If the property's
- // user field is null, then the name of the current user is used
- void putprop(ServerProperty p)
- {
- Message m = new Message();
- m.add("Request","Putprop");
- if (p.user == null) p.user = authname;
- String pstr = p.output();
- byte pb[] = new byte[pstr.length()];
- pstr.getBytes(0, pstr.length(), pb, 0);
- m.setdata(pb);
- m.send(out);
-
- try new Message(in); // errors are ignored
- catch(IOException e);
- }
-
- // delprop
- // Delete a property from the server. If the user parameter is null,
- // the name of the current user is used.
- void delprop(String name, String user)
- {
- Message m = new Message();
- m.add("Request", "Delprop");
- m.add("Property", name);
- m.add("User", user==null ? authname : user);
- m.send(out);
-
- try new Message(in); // errors are ignored
- catch(IOException e);
- }
-
- // rename
- // Send a request to rename one file to another
- void rename(String src, String dst) throws RequestException
- {
- Message m = new Message();
- m.add("Request", "Rename");
- m.add("Source", src);
- m.add("Destination", dst);
- m.send(out);
- getreply();
- }
-
- // purge
- // Delete all versions of a file except for the latest
- void purge(String file) throws RequestException
- {
- Message m = new Message();
- m.add("Request", "Purge");
- m.add("File", file);
- m.send(out);
- getreply();
- }
-
- // chtype
- // Change the MIME type of an existing file
- void chtype(String file, String type) throws RequestException
- {
- Message m = new Message();
- m.add("Request", "Chtype");
- m.add("File", file);
- m.add("Type", type);
- m.send(out);
- getreply();
- }
-
- // send
- // Send an arbitrary message to the server, and read back a reply
- Message send(String req, Message m) throws RequestException
- {
- m.add("Request",req);
- m.send(out);
- return getreply();
- }
-
- // getreply
- // Read a reply from the server, throwing an exception if the
- // reply was a Fail.
- Message getreply() throws RequestException
- {
- Message r = null;
- try r = new Message(in);
- catch(IOException e)
- throw new RequestException("Error reading reply : "+
- e.getMessage());
- if (r.find("Reply").equals("Fail"))
- throw new RequestException(r.find("Reason"));
- return r;
- }
-
- // canaccess
- // Returns true if the current user can access the given file
- // with the given access type.
- boolean canaccess(String file, char p) throws RequestException
- {
- JFSfile fl = statfile(file);
- JFSuser u = uinfo(authname);
- return u.perms(fl).indexOf(p) != -1;
- }
-
- // setcurrent
- // Update the current file, directory and type based on a filename
- void setcurrent(String full) throws RequestException
- {
- setcurrent(full, statfile(full).type);
- }
-
- // setcurrent
- // Update the current file, directory and type based on a filename
- // and type.
- void setcurrent(String full, String type)
- {
- currentdir = full.substring(0, full.lastIndexOf('/')+1);
- currentfile = full.substring(full.lastIndexOf('/')+1);
- currenttype = type;
- }
- }
-
- // RequestException
- // Thrown if a request fails for some reason
- class RequestException extends IOException
- {
- RequestException() { }
- RequestException(String s)
- {
- super(s);
- }
- }
-
- // CutBuffer
- // A buffer shared among multiple JFSclients started (typically) from the
- // same FileBrowser. The buf member points to an object of some type,
- // such as an Image, String or whatever. It should never be null.
- class CutBuffer
- {
- Object buf;
- CutBuffer() { buf = ""; }
- }
-
-