package net.matrix_rad.skang; /* Import external classes that Skang uses. Browsers can download .class files as they are needed, or all at once. Browsers may or may not cache .class files. While a browser would download all the classes in a .zip, .cab, or .jar file all at once, this can reduce the download time required when comparing one compressed download to lots of small uncompressed downloads (unneeded compressed classes versus multiple overheads). This needs to be investigated further to see which is best under what circumstances. Further to that, browsers seem to want to cache Java .class files no matter how you have the caching setup. Netscape requires a shift click on the Reload button to get a fresh copy. IE requires a quit and restart as far as I know. */ import java.lang.*; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.applet.Applet; import java.io.BufferedInputStream; // These are needed for the various methods of getting the skin. import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.EOFException; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; import java.io.StreamTokenizer; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.Calendar; import java.util.Enumeration; import java.util.Date; import java.util.Properties; // So I can store config details in .properties files. import java.util.Hashtable; import java.util.Vector; import net.matrix_rad.security.*; import net.matrix_rad.skang.*; import net.matrix_rad.squeal.Stuff; /** Generic GUI frontend. It allows the actual GUI stuff to be * set from either a network connection or from some other class. * * @.requires Java 1.1 at least. * @author David Seikel * @.copyright 1999 David Seikel * @version 0.722 alpha 2004-11-24 14:30:00 * @.abbreviation ADMIN administrator * @.abbreviation APP application * @.abbreviation AUTH authorization * @.abbreviation INFO information * @.abbreviation MSG message * @.abbreviation NEG negotiation * @.abbreviation NUM number * @.abbreviation OS operating system * @.abbreviation PARAM parameter * @.abbreviation PROT protocol * @.abbreviation RECV receive * @.abbreviation RESP response * @.abbreviation REQ request * #.abbreviation SEP seperation * @.abbreviation SKANG SKin lANGuage * @.abbreviation TEMP temporary * * @.todo Split some or all of the commands out into a seperate module. * @.todo Allow abitrary Thing grouping, for checkbox grouping and GUI tab panes, etc. * * @.fyi Remember that Java Strings are Unicode, and the Net is probably ASCII. It is possible for one programme to be both an application and an applet. Skang is both an application and an applet. Applications use the main(String args[]) entry point, and applets use the init() entry point. * */ public class Skang extends Applet implements Runnable { // Standard broken for this, it should be persistant, and having it first may help. public static int persist = 0; /* Rough execution order for an applet is : init(); void GetParameters(String args[]); String GetParameter(String strName, String args[]); public void start(); public void run(); public void repaint(); public void update(Graphics g); public void paint(Graphics g); public void stop(); public void destroy(); Applications use main(); as the entry point, which will then call init(); Don't use codebase="../whatever", some browsers think it's a security problem. Applet constructors may not have a full environment when called. Some browsers call init() more than once. Some browsers call stop() destroy() when leaving a page, and init() start() when re-entering the page. Applet may not be visible during start() and stop(). Should have init() start a thread for time consuming setup stuff. Good idea to call validate() after creating GUI. I will have to traverse the component tree to find the applet's frame. Remember, applets are Panels. IE4 has a bug, tries to load BeanInfo.class, even if applet is not a bean, provide a dummy BeanInfo.class. update() and paint() get called from the AWT thread, init(), start(), stop() and destroy() DON'T. These are more to do with containers, but defined in Component. void invalidate(); // mark as needing layout. void validate(); // make sure we have a valid layout. void doLayout(); // "prompts layout manager to layout"? These are for all components. void repaint(); // Schedules an update()? void repaint(x, y, w, h); // Only repaint the rectangle void repaint(time); // Time until update() gets called void repaint(time, x, y, w, h); void update(Graphics g); // background not cleared, should call super.update(g) or paint(g). void paint(Graphics g); // When first shown, when needing repair (with a clip rectangle), no need to call super.paint(g). void paintAll(Graphics g); // paint Component, and sub Component These are defined in Container. void invalidate(); void validate(); void validateTree(); // protected void doLayout(); void update(Graphics g); // should call super.update(g) void paint(Graphics g); // should call super.paint(g). void paintComponents(Graphics g); */ /** The main entry point for this class when run as an application. * Sub classes MUST have a main() with the following line -

* Skang.main(someArguments); *

* Think of it as a static super.main(someArguments). * * @param String someArguments[] - The command line arguments, see usage() for details. * @.concurrency Since this method is a wrapper around an applet, it has to start the applet as a thread. * @.example main({"-s", "test.skang"}); */ public static void main(String someArguments[]) { // First, we must be a stand alone application. areWe.setStandAlone(true); // Second, we try to figure out our own name. String ourName = "dunno.Unknown"; Bouncer bouncer = new Bouncer(); if (bouncer != null) { // We don't actually have to install it for our purposes, hope this works everywhere. //SecurityManager oldSecurity = System.getSecurityManager(); //System.setSecurityManager(bouncer); String temp = bouncer.getOurName(); if (temp != null) ourName = temp; //try // {System.setSecurityManager(oldSecurity);} //catch(SecurityException e) // {;} } // Third, we fake an applet. try { Skang skang = (Skang) (Class.forName(ourName).newInstance()); skang.arguments = someArguments; What.root.grokParameters(Parameter.COMMAND, someArguments); // Pretend to be an applet. skang.setStub(areWe); skang.init(); What.areWe.active = true; skang.start(); } catch (ClassNotFoundException e) {What.ERRLN("main() Class not found " + e.toString() + " " + e.getMessage());} catch (IllegalAccessException e) {What.ERRLN("main() IllegalAccess " + e.toString() + " " + e.getMessage());} catch (IllegalArgumentException e) {What.ERRLN("main() IllegalArgument " + e.toString() + " " + e.getMessage());} catch (InstantiationException e) {What.ERRLN("main() Instantiation " + e.toString() + " " + e.getMessage());} catch (Exception e) {What.ERRLN("main() Exception " + e.toString() + " " + e.getMessage());} } /** Called by the AWT when an applet is first loaded or reloaded. * * @.fyi NEVER put a popUp in init(), put them in start() instead. init() * sometimes has a limited time to run before the browser complains. */ public void init() { areWe.destroying = false; //ERRLN("->Skang.init() FOR " + this.getClass().getName()); super.init(); if (What.me == null) { What.me = this; What.areWe = areWe; if (!areWe.standAlone) What.appCodeBase = getCodeBase(); String name = this.getClass().getName(); if (security == null) security = new Fascist(); What.root.user = new Who(name); What.modulesDisplay = "MODULES :"; if (!name.equals(SKANG_NAME)) new Module(What.root, SKANG_NAME, new Skang(), this); new Module(What.root, name, this, this); Enumeration modules = Thing.elements(What.root, Module.type); while (modules.hasMoreElements()) { Leaf leaf = (Leaf) modules.nextElement(); if (!(leaf.getValue() instanceof Module)) continue; Module module = (Module) leaf.getValue(); if ((!module.name.equals(name)) && (!module.name.equals(SKANG_NAME)) && !module.isStub) { //ERRLN("->Skang.init() FOR " + this.getClass().getName() + " - RE INITING " + module.name); What.modulesDisplay += " " + module.name.substring(module.name.lastIndexOf('.') + 1); try {module.module.init();} catch (Exception e) {ERRLN("Skang.init()->" + module.name + ".init() " + e.toString()); e.printStackTrace();} } } What.root.regrokAppletParameters(What.me); What.corporateShit = What.isBoolean(corporate).booleanValue(); What.isInBrowser = What.isBoolean(inBrowser).booleanValue(); What.isPHP = What.isBoolean(PHP).booleanValue(); pendingDoThing("skang"); if ((!What.areWe.servlet) && (!What.areWe.standAlone)) servletPendingDoThing(What.root, "load '" + name + "'"); } //ERRLN("->Skang.init() FOR " + this.getClass().getName() + " ENDED"); persist++; } /** Initialize the GUI stuff. * Just an empty method for others to override. Yes, I know GUI code * has no place in this class, but there ain't any actual GUI code here B-). * Override this to do any init stuff that needs to be done after the GUI * is setup. Usually used for finding particular widgets, or filling * some widgets with things that Skang can't do. */ public void initGUI() { //ERRLN("->Skang.initGUI() FOR " + this.getClass().getName()); initGUIDone = true; } // Should make this a waitForThing() public boolean waitForGUI(String aName) { boolean result = true; int count = 0; Widget widget = null; do { pause(10); if (!this.initGUIDone) this.initGUI(); try {widget = Widget.getWidget(aName);} catch (Exception e) {;} count++; if (count > 10) { ERRLN("*** " + aName + " widget NOT FOUND!!!"); result = false; } } while ((result) && (widget == null)); return result; } /** Called when an applet is first shown in a browser window. Starts the * applets main thread. */ public void start() { if (persist > 3) // stop() called without destroy() { // Try to work around one of the applet repaint bugs. What.appToolkit.beep(); OUTLN("REPAINT BUG WORK AROUND!!!"); OUTLN("REPAINT BUG WORK AROUND!!!"); OUTLN("REPAINT BUG WORK AROUND!!!"); What.appToolkit.beep(); Skang me = What.me; What.me.destroy(); me.init(); } What.areWe.active = true; areWe.stoping = false; areWe.starting = true; //ERRLN(this.getClass().getName() + "->Skang.start()"); if (this.m_Skang == null) { this.m_Skang = new Thread(this, this.getClass().getName() + "->Skang"); this.m_Skang.start(); } areWe.starting = false; persist++; } /** Skangs main loop. * Don't overide this, override runBit() instead. * * @.modifies What.areWe.active * @.concurrency the main thread. */ public final void run() { //ERRLN(this.getClass().getName() + "->Skang.run()"); while (!areWe.stoping) pause(10); What.areWe.active = false; } /** Spend some quality time with the scheduler B-). * A wrapper around sleep() so that we don't have to fill source with try/catch * everytime we just want a delay. */ public final void pause(int aDelay) { while ((aDelay > 0) && (!areWe.stoping)) { try { runBits(); Thread.sleep(10); aDelay -= 10; } catch (InterruptedException e) {break;} } } /** Every modules threaded method. * Skang calls this on a regular basis during it's run loop. * The default runBit() just does nothing. */ public void runBit() { } /** Run all the runBit()'s of all the modules. */ private void runBits() { //ERRLN("->Skang.runbit() " + this.getClass().getName()); try { while (!What.root.ToDo.isEmpty()) { String command = (String) What.root.ToDo.firstElement(); What.root.ToDo.removeElementAt(0); // index is zero based. if (command != null) doThing(command); } if ((!areWe.servlet) && (!areWe.standAlone)) { if (!What.root.servletToDo.isEmpty()) { String clas = What.me.getClassName(); What.me.postParseThings(What.root, "/" + servletPath + "/" + clas.toLowerCase() + ".svlt"); } } } catch (Exception e) {;} int k = 0; Enumeration modules = Thing.elements(What.root, Module.type); String newModulesDisplay = ""; if (modules.hasMoreElements()) { newModulesDisplay = "MODULES :"; String noModulesDisplay = " BROKEN :"; boolean brokenModules = false; while (modules.hasMoreElements()) { Leaf leaf = (Leaf) modules.nextElement(); if (!(leaf.getValue() instanceof Module)) continue; Module mod = (Module) leaf.getValue(); String name = mod.name.substring(mod.name.lastIndexOf('.') + 1); String why = null; Module thing = null; try { Skang module = mod.module; if (module != null) { if ((!areWe.servlet) && (counter == 0) && (nextCopyright == k)) showCopyright(module); if (areWe.quitting) { module.quit(); } // Should do this better. else if (module.initGUIDone) module.runBit(); } else throw(new SkangException("No module")); } catch (Exception e) {why = e.getMessage();} if (why == null) newModulesDisplay += " " + name; else { noModulesDisplay += " " + name + " " + why; brokenModules = true; if (thing != null) thing.hasCrashed++; // doThing("disable \"Gnome\""); } k++; } if (brokenModules) newModulesDisplay += noModulesDisplay; } if (!newModulesDisplay.equals(What.modulesDisplay)) { What.modulesDisplay = newModulesDisplay; What.isNewTree = true; } counter++; if (counter >= 200) // See the note at the bottom of showCopyright() about excessive documentation B-). { counter = 0; nextCopyright++; if (nextCopyright >= k) nextCopyright = 0; } if (areWe.quitting) { What.me.stop(); What.me.destroy(); if ((!areWe.servlet) && (areWe.standAlone)) System.exit(0); } //ERRLN("->Skang.runbit() " + this.getClass().getName() + " - END"); } /** Called when an applet is no longer shown in a browser window. Stops the * applets main thread. Can also be called to kill the applet. */ public void stop() { What.areWe.active = false; areWe.stoping = true; //ERRLN(this.getClass().getName() + "->Skang.stop()"); if (this.m_Skang != null) { this.m_Skang = null; } persist++; } public void destroy() { areWe.destroying = true; currentState = IDLE; //ERRLN(this.getClass().getName() + "->Skang.destroy()"); Enumeration modules = Thing.elements(What.root, Module.type); while (modules.hasMoreElements()) { Leaf leaf = (Leaf) modules.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Module) { Module thing = (Module) leaf.getValue(); Skang module = thing.module; if ((module != null) && (!thing.name.equals("net.matrix_rad.zen.Developer"))) module.initGUIDone = false; } } } if (!areWe.servlet) doThing("clear"); What.root.stripSome(null); What.me = null; // Should probably tickle the GC now. System.runFinalization(); System.gc(); persist = 0; } /** Provides browsers with some info about this applet. */ public final String getAppletInfo() { String returnString = ""; try {returnString += "Name: " + getClassName() + ".class\n";} catch (Exception e) {;} try {returnString += "Version: " + skanglet.VERSION + "\n";} catch (Exception e) {;} try {returnString += "Author: " + skanglet.AUTHOR + "\n";} catch (Exception e) {;} try {returnString += "Copyright: " + skanglet.COPYRIGHT + "\n";} catch (Exception e) {;} return returnString; } /** Provides an array of information about the applets parameters. */ public final String[][] getParameterInfo() { int i = 0; // try { Enumeration things = Thing.elements(What.root, Parameter.type); while (things.hasMoreElements()) { Leaf leaf = (Leaf) things.nextElement(); if (leaf != null) if (leaf.getValue() instanceof Parameter) i++; } String parameterInfo[][] = new String[i][3]; i = 0; things = Thing.elements(What.root, Parameter.type); while (things.hasMoreElements()) { Leaf leaf = (Leaf) things.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Parameter) { Parameter usage = (Parameter) leaf.getValue(); parameterInfo[i][0] = usage.name; parameterInfo[i][1] = usage.toClassString(); parameterInfo[i][2] = usage.help; i++; } } } return parameterInfo; } // catch (ThingNotFoundException e) // {;} // return null; } /** Just an empty method for others to override. */ public void quit() { //ERRLN("->Skang.quit() " + this.getClass().getName()); } public static String OUT(String aValue) { return What.OUT(aValue); } public static String OUTLN(String aValue) { return What.OUTLN(aValue); } public static String ERR(String aValue) { return What.ERR(aValue); } public static String ERRLN(String aValue) { return What.ERRLN(aValue); } //********************************************************************** /** Source files that the system cannot infer from other evidence. */ public final static String[] CLASS_SOURCE_FILES = { "Example.java", "SkangletBase.java", "Thing.java", "What.java", }; /** Argument types recognised by Skang. */ public final static String[][] SKANG_ARGS = { {"name", "java.lang.String"}, {"action", "java.lang.String"}, {"type", "java.lang.String"}, {"data", "java.lang.String"}, {"URL", "java.lang.String"}, {"file", "java.lang.String"}, {"method", "java.lang.String"}, {"lx", "java.lang.String"}, {"ly", "java.lang.String"}, {"lw", "java.lang.String"}, {"lh", "java.lang.String"}, {"normal", "java.lang.String"}, {"ghost", "java.lang.String"}, {"active", "java.lang.String"}, {"toggle", "java.lang.String"}, {"boolean","java.lang.Boolean"}, {"number", "java.lang.Integer"}, {"int", "java.lang.Integer"}, {"x", "java.lang.Integer"}, {"y", "java.lang.Integer"}, {"w", "java.lang.Integer"}, {"h", "java.lang.Integer"}, {"r", "java.lang.Integer"}, {"g", "java.lang.Integer"}, {"b", "java.lang.Integer"}, {"alpha", "java.lang.Integer"}, {"acl", "net.matrix_rad.security.ACL"}, {"", ""}, }; /** Default state for the state machine. */ public final static short IDLE = 0; public final static String SKANG_NAME = "net.matrix_rad.skang.Skang"; //********************************************************************** public static String calendarToDate(Calendar aCalendar) { return("" + What.padString("0000", "" + aCalendar.get(Calendar.YEAR)) + "-" + What.padString("00", "" + (aCalendar.get(Calendar.MONTH) + 1)) + "-" + What.padString("00", "" + aCalendar.get(Calendar.DATE)) + " "); } public static String calendarToTime(Calendar aCalendar, boolean doHundredths) { return("" + What.padString("00", "" + aCalendar.get(Calendar.HOUR_OF_DAY)) + ":" + What.padString("00", "" + aCalendar.get(Calendar.MINUTE)) + ":" + What.padString("00", "" + aCalendar.get(Calendar.SECOND)) + (doHundredths ? ("." + What.padString("00", "" + (aCalendar.get(Calendar.MILLISECOND) / 10))) : "") + " "); } public String format(int number, int length) { String result = "0000000000000000000000000000000000000000000000000000000000000" + (new Integer(number)).toString(); int len = result.length(); try {result = result.substring(len - length, len);} catch (Exception e) {result = (new Integer(number)).toString();} return result; } public String format(long number, int length) { String result = "0000000000000000000000000000000000000000000000000000000000000" + (new Long(number)).toString(); int len = result.length(); try {result = result.substring(len - length, len);} catch (Exception e) {result = (new Long(number)).toString();} return result; } public String format(double number, int length) { String result = (new Double(number)).toString() + "0000000000000000000000000000000000000000000000000000000000000"; int len = result.length(); try {result = result.substring(0, length);} catch (Exception e) {result = (new Double(number)).toString();} return(result); } public String getClassName() { String result = this.getClass().getName(); int dotPos = result.lastIndexOf('.'); if (dotPos != -1) result = result.substring(dotPos + 1); return result; } public String getPackageName() { String result = this.getClass().getName(); int dotPos = result.lastIndexOf('.'); if (dotPos != -1) result = result.substring(0, dotPos); else result = ""; return result; } /** Increment the state. * * @.precondition currentState must already be a valid state. * @.modifies currentState * @.concurrency All access to currentState must be synchronized. */ public synchronized void nextState() { currentState++; } public InputStream openResource(String aFile) { //ERRLN("openResource(" + aFile + ")"); InputStream in = null; Class me = this.getClass(); aFile = aFile.replace('\\', '/'); // For hard coded slashes. try { ClassLoader loader = me.getClassLoader(); in = loader.getResourceAsStream(aFile); } catch (Exception e) {;} if (in == null) { try { in = openFile(aFile); // Netscape is too anal, open it the old fashioned way. ERRLN(" "); } catch (Exception e1) {ERRLN(e1.getMessage()); e1.printStackTrace();} } return in; } public static InputStream openFile(String aFile) throws SkangException { //ERRLN("openFile(" + aFile + ")"); InputStream input = null; int pos = aFile.indexOf("?"); try { if (!areWe.standAlone) { aFile = aFile.replace('\\', '/'); // For hard coded slashes. URLConnection web; if (pos != -1) // Do a POST. { // ERRLN("POSTING " + (new URL(What.appCodeBase, aFile.substring(0, pos))).toString() + " " + aFile.substring(pos + 1)); // And quickly scroll it out of the status line. ERRLN("Requesting data from the server."); web = (new URL(What.appCodeBase, aFile.substring(0, pos))).openConnection(); web.setDoOutput(true); web.setUseCaches(false); web.setAllowUserInteraction(false); PrintWriter out = new PrintWriter(web.getOutputStream()); out.print(aFile.substring(pos + 1)); out.close(); //BufferedReader in = new BufferedReader(new InputStreamReader(web.getInputStream())); //String text; //while ((text = in.readLine()) != null) // ERRLN(text); } else { web = (new URL(What.appCodeBase, aFile)).openConnection(); web.setUseCaches(false); web.setAllowUserInteraction(false); } input = web.getInputStream(); } else { aFile = aFile.replace('/', What.separator); // For hard coded slashes. aFile = aFile.replace('\\', What.separator); // For hard coded slashes. input = new FileInputStream(aFile); } } catch (EOFException e) {throw(new SkangException("Lost connection to file." + e.toString()));} catch (MalformedURLException e) {throw(new SkangException("Malformed URL " + e.toString()));} catch (IOException e) {throw(new SkangException("..IOException " + e.toString()));} return input; } private String parseTheSkang(String aString) { return this.parseTheSkang(new StringReader(aString)); } private String parseTheSkang(ThingSpace myRoot, String aString) { return this.parseTheSkang(myRoot, new StringReader(aString)); } private String parseTheSkang(String aString[]) { String temp = ""; for (int i = 0; i < aString.length; i++) temp += aString[i] + "\n"; return this.parseTheSkang(new StringReader(temp)); } private String parseTheSkang(Reader aReader) { return this.parseTheSkang(What.root, aReader); } private String parseTheSkang(ThingSpace myRoot, Reader aReader) { // Should use more of this array, instead of the current hard coded shit. /* {"clear", "clearWidgets", "", "The current skin is cleared of all widgets."}, {"add", "addWidget", "name,type,lx,ly,lw,lh,data,other", "Add a widget to the current skin."}, {"look", "lookWidget", "name,normal,ghost,active,toggle", "Set the current look of an existing widget."}, {"tell", "tellWidget", "name", "Returns details of an existing widget."}, {"get", "getWidget", "name", "Get the current value of an existing widget."}, {"set", "setWidget", "name,data", "Set the current value of an existing widget."}, {"", "", "", "", "", "", ""} */ String result = null; String line = ""; Vector struct = new Vector(); boolean doDot = false; boolean doPane = false; boolean doSet = false; boolean doStruct = false; Object temp[] = new Object[20]; int argCount = 0; int type = 0; StreamTokenizer input = new StreamTokenizer(aReader); input.resetSyntax(); input.parseNumbers(); input.eolIsSignificant(true); input.slashStarComments(true); input.slashSlashComments(true); input.whitespaceChars('\u0000', '\u0020'); input.whitespaceChars(',', ','); input.wordChars('a', 'z'); input.wordChars('A', 'Z'); input.wordChars('[', '['); input.wordChars(']', ']'); input.wordChars('$', '$'); input.wordChars('#', '#'); input.wordChars('!', '!'); input.wordChars('\\', '\\'); input.wordChars('\u00A0', '\u00FF'); input.ordinaryChar('='); input.ordinaryChar('_'); input.ordinaryChar('{'); input.ordinaryChar('}'); input.quoteChar('"'); input.quoteChar('\''); try { do { if (doDot) doDot = false; else if (doSet && (argCount > 2)) type = StreamTokenizer.TT_EOL; else { input.nextToken(); type = input.ttype; } switch (type) { case StreamTokenizer.TT_WORD : case '"' : case '\'' : // Should If argCount == 0, then this is the command, try to find it now, so we know what args to expect, // unless this turns out to be doSet or doJava, which we won't know until later, // so don't be surprised if we can't find the command, that's not an error now. // Fix the "Nasty hack" below once this works. // Should If the name of some Thing is passed as an argument, find it's object and pass it along as an // argument to the Command, but only if argument type is arg or args. if (doStruct) { if (type == '"') line += "\"" + input.sval+ "\" "; else if (type == '\'') line += "'" + input.sval+ "' "; else line += input.sval+ " "; } else { temp[argCount++] = (Object) input.sval; } break; case StreamTokenizer.TT_NUMBER : if (doStruct) { line += "" + ((int) input.nval) + " "; } else { if ((argCount > 0) && temp[0].toString().equals("widget")) // Nasty hack. temp[argCount++] = (Object) ("" + ((int) input.nval)); else temp[argCount++] = (Object) new Integer((int) input.nval); } break; case StreamTokenizer.TT_EOF : case StreamTokenizer.TT_EOL : if (doStruct) { if ((line != null) && (!line.equals(""))) { line = line.substring(0, line.length() - 1); struct.addElement(line); } line = ""; } else { if (argCount > 0) { String commandOut = (String) temp[0]; for (int j = 1; j < argCount; j++) { if (temp[j] != null) { if (temp[j] instanceof String) commandOut += " '" + temp[j].toString() + "'"; else commandOut += " " + temp[j].toString(); } } // temp[0] = (Object) ((String) temp[0]).toLowerCase(); try { //ERR("EXECUTING " + temp[0] + " "); Command command = Command.getCommand((String) temp[0]); Object args[] = null; if (argCount > 1) { args = new Object[argCount - 1]; // Class classes[] = new Class[argCount]; for (int i = 0; i < (argCount - 1); i++) { // Should probably convert String to Boolean or whatever the argument type is. args[i] = temp[i + 1]; // Don't need the method name as an argument. } } if (showCommands) OUTLN(">>>" + commandOut); What.UBER(commandOut); Object returnObject = null; returnObject = command.invoke(myRoot, this, args); if (returnObject != null) { try { String tempResult = null; if (returnObject instanceof Boolean) { if (((Boolean) returnObject).booleanValue()) tempResult = "True"; else tempResult = "False"; } else if (returnObject instanceof Integer) tempResult = "" + returnObject; else tempResult = (String) returnObject; if (result == null) result = tempResult; else result += "\n" + tempResult; } catch (Exception e) {;} } } catch (InvocationTargetException e) { Throwable e1 = e.getTargetException(); ERR("INVOKE ERROR - " + this.getClass().getName() + "." + temp[0] + "("); for (int j = 0; j < (argCount - 1); j++) { ERR(temp[j + 1].getClass().getName()); try {ERR(" " + ((String) temp[j + 1]) + ", ");} catch (Exception ex1) {ERR(" " + temp[j + 1].toString() + ", ");} } ERRLN(") - " + e1.toString() + " " + e1.getMessage()); e1.printStackTrace(); } catch (Exception e) { ERR("ERROR - " + this.getClass().getName() + "." + temp[0] + "("); for (int j = 0; j < (argCount - 1); j++) { ERR(temp[j + 1].getClass().getName()); try {ERR(" " + ((String) temp[j + 1]) + ", ");} catch (Exception ex1) {ERR(" " + temp[j + 1].toString() + ", ");} } ERRLN(") - " + e.toString() + " " + e.getMessage()); e.printStackTrace(); } argCount = 0; doDot = false; doPane = false; doSet = false; } } break; case '_' : input.nextToken(); type = input.ttype; if (type != StreamTokenizer.TT_NUMBER) temp[argCount - 1] = temp[argCount - 1] + "_" + input.sval; else temp[argCount++] = "_" + ((int) input.nval); break; case '.' : doPane = true; input.nextToken(); type = input.ttype; if (type == StreamTokenizer.TT_WORD) temp[argCount - 1] = temp[argCount - 1] + "." + input.sval; else doDot = true; break; case '=' : if (argCount == 1) { doSet = true; temp[1] = (Object) temp[0]; // Name of some Thing. temp[0] = (Object) "set"; argCount = 2; } break; case '{' : doStruct = true; line = ""; struct = new Vector(); input.wordChars('!', '!'); input.wordChars('#', '&'); input.wordChars('(', ')'); input.wordChars('+', '.'); input.wordChars('0', 'z'); input.wordChars('|', '|'); // input.wordChars('"', '"'); // input.wordChars('\'', '\''); input.wordChars('*', '*'); input.wordChars('_', '_'); input.wordChars('.', '.'); input.wordChars('\u007E', '\u00FF'); argCount = 0; doDot = false; doPane = false; doSet = false; break; case '}' : doStruct = false; input.whitespaceChars(',', ','); input.ordinaryChar('='); input.ordinaryChar('_'); // input.ordinaryChar('.'); // input.ordinaryChar('{'); // input.ordinaryChar('}'); input.quoteChar('"'); input.quoteChar('\''); if (!struct.isEmpty()) { // get the first word of the first line line = (String) struct.elementAt(0); if (showCommands) OUTLN(">>>{ " + line); //ERRLN("STRUCT |" + line + "|"); int pos = line.indexOf(' '); int count = struct.size(); String clas = ""; Struct data = null; if (pos != -1) { clas = line.substring(0, pos); line = line.substring(pos + 1); } // line = line.substring(0, line.length() - 1); // find a matching Thing class (Widget, Stuff) // No point matching to Collision, Module, CLASS_CACHE // Maybe Command - define a skang subroutine // Maybe Parameter - an actual struct! // Maybe Tab - to group widgets for a Tab area. // This implies that {} can be nested though. if (clas.equals("Stuff")) data = Stuff.initStruct(myRoot, line); else if (clas.equals("Widget")) data = Widget.initStruct(myRoot, line); else if (clas.equals("Whinge")) data = Whinge.initStruct(myRoot, line); if (data != null) { // for each line for (int i = 1; i < count; i++) { line = ((String) struct.elementAt(i)).trim(); if (showCommands) OUTLN(">>> " + line); // line = line.substring(0, line.length() - 1); if ((line != null) && (!line.equals(""))) data.moreStruct(line.charAt(0), line.substring(1).trim()); } data.finishStruct(); } if (showCommands) OUTLN(">>>}"); } struct = new Vector(); line = ""; break; default : break; } } while (type != StreamTokenizer.TT_EOF); } catch (IOException e) {ERRLN("IOException during parsing " + e.toString() + " " + e.getMessage()); e.printStackTrace();} return result; } /** Read a properties file. * * @param String aString - The file name, without the .properties extension. * @.example readProperties("BPC_NO"); */ public static Properties readProperties(String aFile) { Properties aProp = new Properties(); aFile += ".properties"; ERRLN("Loading properties - " + aFile); What.doRedirect(); try { aProp.load(What.me.openResource(aFile)); ERRLN(""); } catch (SecurityException e) {ERRLN("Access to " + aFile + " not permitted: " + e.toString());} catch (IOException e) {ERRLN("Unable to read from " + aFile + ": " + e.toString());} catch (NullPointerException e) {ERRLN("NULL Unable to open " + aFile + ": " + e.toString());} catch (Exception e) {ERRLN("Unable to open " + aFile + ": " + e.toString());} What.doRedirect(); return(aProp); } /** Run some OS executable with out and err redirection. */ public int runProgram(String aTitle, String aCommand) { areWe.waiting = true; int returnValue = 999; Runtime rt = Runtime.getRuntime(); try { Process proc = rt.exec(aCommand); BufferedReader out = new BufferedReader(new InputStreamReader(proc.getInputStream())); BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); // Redirect out/err. do { try { runBits(); Thread.sleep(10); } catch (InterruptedException e) {;} // Watch this, may need to put a break here, or rethrow the exception. try {returnValue = proc.exitValue();} catch (IllegalThreadStateException e) {;} if (out.ready()) try {OUTLN(" o " + aTitle + " : " + out.readLine());} catch (IOException e) {;} if (err.ready()) try {ERRLN(" e " + aTitle + " : " + err.readLine());} catch (IOException e) {;} } while ((returnValue == 999) && (!areWe.stoping)); } catch (Exception e) {ERRLN("-1" + e.toString()); e.printStackTrace();} if (returnValue == 0) ERRLN(" " + aTitle + " : WORKED!"); else ERRLN(" " + aTitle + " : FAILED - " + returnValue + "!"); areWe.waiting = false; return returnValue; } /** Set the state. * * @.precondition currentState must already be a valid state. * @param short aCurrentState - State to change to. * @.modifies currentState * @.concurrency All access to currentState must be synchronized. * @.example setState(IDLE_LOGIN) */ public synchronized void setState(short aCurrentState) { //ERRLN("SETSTATE " + aCurrentState + " FOR - " + this.getClass().toString()); currentState = aCurrentState; } public void showCopyright(Skang aModule) { if (aModule == null) return; if (aModule.skanglet == null) return; String version = "" + aModule.skanglet.version; if (initGUIDone) { if (isGnome) pendingDoThing("enable \"Gnome\""); else pendingDoThing("disable \"Gnome\""); isGnome = !isGnome; String action = aModule.getClassName() + " " + version + " Copyright " + aModule.skanglet.COPYRIGHT + "."; pendingDoThing("set \"Copyright\", '" + action + "'"); } counter = 1; // Reset the counter so that we are shown for the usual period if this is a hover. // Reset to 1 to avoid retriggering the runbit rotate. // How much comment can you get out of a simple assignment B-). } /** Output usage details. */ public void usage() { usage(""); } /** Output an optional error message and usage details. * * @param String aReason - The reason you are being shown the usage instructions. * @.example usage("No username supplied."); */ private void usage(String aReason) { if (aReason != "") { ERRLN("ERROR: " + aReason); ERRLN(""); } try { ERRLN(getClassName() + ".class " + skanglet.VERSION + ":"); ERRLN("[RCS $Id: " + getClassName() + ".class,v " + skanglet.VERSION + " dvs1 Exp dvs1 $]"); } catch (Exception e) {;} // ERRLN("[RCS $Id: Skang.java,v 1.4 2000/12/08 01:41:46 dvs1 Exp $]"); ERRLN(""); ERR("Usage:"); // try { Enumeration things = Thing.elements(What.root, Parameter.type); while (things.hasMoreElements()) { Leaf leaf = (Leaf) things.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Parameter) { Parameter usage = (Parameter) leaf.getValue(); String command = "--" + usage.name; if (usage.shortcut != "") command = "-" + usage.shortcut; if (!usage.isRequired) ERR(" [" + command); else ERR(" " + command); if (!usage.fieldName.endsWith(")")) ERR(" " + usage.fieldName); if (!usage.isRequired) ERR("]"); } } } ERRLN(""); things = Thing.elements(What.root, Parameter.type); while (things.hasMoreElements()) { Leaf leaf = (Leaf) things.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Parameter) { Parameter usage = (Parameter) leaf.getValue(); String command = "--" + usage.name; if (usage.shortcut != "") command = "-" + usage.shortcut; ERRLN(""); ERR(" '" + command); if (!usage.fieldName.endsWith(")")) ERR(" (" + usage.fieldName + ")"); ERR("' "); if (usage.isRequired) ERRLN("(required)"); else ERRLN("(optional)"); ERRLN(" " + usage.help); } } } } // catch (ThingNotFoundException e) // { // ERRLN("Help system broken, sorry."); // } System.exit(1); } /****************************************************************************************************** Skang keywords. ******************************************************************************************************/ /** Load a module. * * @.skang module file,data * @.todo support module "net.matrix_rad.watch.Watch --modes 'A AM'" */ public void addModule(ThingSpace myRoot, String aModule) { addModule(myRoot, aModule, ""); } public void addModule(ThingSpace myRoot, String aModule, String acl) { //ERRLN("->addModule(" + aModule + ") FOR " + this.getClass().getName()); if (aModule == null) return; try {Module.getModule(aModule);} // If we have never added this module... catch (ThingNotFoundException e) // ...add it. { OUTLN("Loading module - " + aModule); What.doRedirect(); Module module = new Module(myRoot, aModule, "", acl, What.me); OUTLN(""); } } /** Append to the current value of a Thing. * * @.skang append name,data */ public void appendThing(String aName, String aValue) throws SkangException { Thing.appendText(aName, aValue); } /** A not so clever unix script compatability hack. * * @.skang #!java name,name,name,name,name,name,name */ public void bash(String aName, String anotherName, String yetAnotherName, String someOtherName, String notherName, String ahhhhName, String fuckIveRunOutOfPrefixesName) { } public void bash(String aName, String anotherName, String yetAnotherName, String someOtherName, String notherName, String ahhhhName) { } public void bash(String aName, String anotherName, String yetAnotherName, String someOtherName, String notherName) { } public void bash(String aName, String anotherName, String yetAnotherName, String someOtherName) { } public void bash(String aName, String anotherName, String yetAnotherName) { } public void bash(String aName, String anotherName) { } public void bash(String aName) { } /** Do an action when you are ready. * * @.skang pending action * */ public static void pendingDoThing(String anAction) { pendingDoThing(What.root, anAction); } public static void pendingDoThing(ThingSpace myRoot, String anAction) { myRoot.ToDo.addElement(anAction); } public static void appletPendingDoThing(ThingSpace myRoot, String anAction) { if (!areWe.standAlone) myRoot.ToDo.addElement(anAction); else myRoot.appletToDo.addElement(anAction); } public static void servletDoPendingThings(ThingSpace myRoot) { try { if (!myRoot.servletToDo.isEmpty()) { String anURL = "/" + servletPath + "/skang.svlt"; What.me.postParseThings(myRoot, anURL); } } catch (Exception e) {;} } public static void servletPendingDoThing(ThingSpace myRoot, String anAction) { if (areWe.servlet) myRoot.ToDo.addElement(anAction); else myRoot.servletToDo.addElement(anAction); } /** Only do this if we are an applet. * * @.skang applet action */ public String doIfApplet(ThingSpace myRoot, String anAction) { String result = null; if (!areWe.standAlone) result = parseTheSkang(myRoot, anAction); return result; } /** Only do this if we are an application. * * @.skang application action */ public String doIfApplication(ThingSpace myRoot, String anAction) { String result = null; if (areWe.standAlone && !areWe.servlet) result = parseTheSkang(myRoot, anAction); return result; } /** Only do this if we are doing corporate shit. * * @.skang corporateshit action */ public String doIfCorporateShit(ThingSpace myRoot, String anAction) { String result = null; if (What.corporateShit) result = parseTheSkang(myRoot, anAction); return result; } /** Only do this if we are in the real world. * * @.skang realworld action */ public String doIfRealWorld(ThingSpace myRoot, String anAction) { String result = null; if (!What.corporateShit) result = parseTheSkang(myRoot, anAction); return result; } /** Only do this if we are a servlet. * * @.skang servlet action */ public String doIfServlet(ThingSpace myRoot, String anAction) { String result = null; if (areWe.servlet) result = parseTheSkang(myRoot, anAction); return result; } /** Do this action. * * @.skang do action */ public String doThing(String anAction) { return doThing(What.root, anAction); } public String doThing(ThingSpace myRoot, String anAction) { //ERRLN("->doThing() " + anAction + " FOR " + this.getClass().getName()); return parseTheSkang(myRoot, anAction); } /** * A dummy function for unimplemeted commands. */ public void dontThing(String aName) { return; } /** Grab a file from a URL. * * @.skang grab URL * @param String aURL - the URL to grab. * @throws SkangException text */ public void getFile(String aURL) throws SkangException { aURL = aURL.replace('\\', '/'); // For hard coded slashes. OUTLN(aURL + " connecting..."); try { int len = 0; int total = 0; int subTotal = 0; byte buffy[] = new byte[10 *1024]; URL web = new URL(aURL); URLConnection webConnection = (URLConnection) web.openConnection(); webConnection.setAllowUserInteraction(false); InputStream input = webConnection.getInputStream(); String file = webConnection.getURL().getFile(); Date date = new Date(webConnection.getLastModified()); if (file.endsWith("/")) file += "index.html"; // A default name. String destination = (downloadDir + file).replace('/', What.separator); String dir = destination.substring(0, destination.lastIndexOf(What.separator)); (new File(dir)).mkdirs(); runBits(); OUTLN( webConnection.getURL().getProtocol() + "://" + webConnection.getURL().getHost() + ":" + webConnection.getURL().getPort() + file + " is " + webConnection.getContentType() + ", last modified " + date.toGMTString() + ", downloading " + webConnection.getContentLength() + " bytes to " + destination); BufferedInputStream in = new BufferedInputStream(input); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destination)); long startTime = System.currentTimeMillis(); long thisTime = startTime; long bytes = webConnection.getContentLength(); ERRLN(">> " + destination + " got " + total + " of " + bytes); while (((len = in.read(buffy, 0, buffy.length)) != -1) && (!areWe.stoping)) { total += len; subTotal += len; out.write(buffy, 0, len); if (((System.currentTimeMillis() - thisTime) > 1000) || (total == bytes)) // Don't update more than once a second. { double thisSeconds = (System.currentTimeMillis() - thisTime) / 1000.0; double rate = (thisSeconds != 0) ? ((subTotal / thisSeconds) / 1024.0) : 0.0; thisTime = System.currentTimeMillis(); subTotal = 0; double seconds = (System.currentTimeMillis() - startTime) / 1000.0; double average = (seconds != 0) ? ((total / seconds) / 1024.0) : 0.0; long minutes = ((long) seconds) / 60; long hours = minutes / 60; seconds -= minutes * 60; minutes -= hours * 60; ERRLN(">> " + destination + " got " + total + " of " + bytes + " in " + format(hours, 2) + ":" + format(minutes, 2) + ":" + format(((long) seconds), 2) + " @ " + format(rate, 5) + " (" + format(average, 5) + ") KB/s"); if (What.uberMatrix != null) { try {What.UBER(new String(buffy, 0, len, What.encoding));} catch (Exception e) {;} } } runBits(); } out.flush(); out.close(); try {helpThing(destination.replace(What.separator, '/') + (destination.startsWith("/") ? "" : "/"));} catch (Exception e) {;} } catch (Exception e) // It's only important that there was an error. {throw(new SkangException("problem getting " + aURL + " : " + e.toString()));} } /** Get the current value of an existing thing. * * @.skang get name */ public String getThing(String aName) throws SkangException { return getThing(What.root, aName); } public String getThing(ThingSpace myRoot, String aName) throws SkangException { return getThing((Thing) Thing.get(myRoot, aName)); } public String getThing(Thing aThing) throws SkangException { String returnString = null; try { Object args[] = new Object[1]; returnString = aThing.get.invoke(aThing.thing, null).toString(); if (aThing.isValid != null) { try { String complaint = (String) aThing.isValid.invoke(this, args); if (complaint.equals("")) { ERRLN(" "); // BotLabRight.setBackground(Color.white); } else { returnString = null; ERRLN("Invalid " + aThing.name + " - " + complaint + "!"); // BotLabRight.setBackground(Color.red); // Should throw an exception } } catch (Exception e) {;} } } catch (Exception e) {;} return returnString; } /** Returns the modules default skin. * * @.skang gimmeskin */ public String gimmeSkin() { String returnString = "\n"; try { String skang[] = What.me.skanglet.DEFAULT_SKANG; for (int i = 0; i < skang.length; i++) returnString += skang[i] + "\n"; } catch (Exception e) {;} return(returnString); } /** Show help page. * * @.skang help file */ public void helpThing() throws SkangException { helpThing(null); } public void helpThing(String aFile) throws SkangException { String args[] = new String[2]; String aBrowser = browser; boolean isHelp = false; if (aFile == null) { isHelp = true; aFile = "docs/" + What.me.getClass().getName().replace('.', What.separator) + ".html"; } if (areWe.standAlone) { aFile = "file://" + System.getProperty("user.home") + "/matrix-RAD/" + aFile; // Should make this more idiot proof later. // file://~/matrix/docs/%f // Do parameter substitution on browser. // Doing it backwards prevents expanding the substitution, which can result in endless loops. for (int pos = aBrowser.length(); (pos = aBrowser.lastIndexOf("~", pos)) != -1; ) // Substitute the home dir - ~ aBrowser = aBrowser.substring(0, pos) + System.getProperty("user.home") + aBrowser.substring(pos + 2, aBrowser.length()); for (int pos = aBrowser.length(); (pos = aBrowser.lastIndexOf("%w", pos)) != -1; ) // Substitute the working dir - %w aBrowser = aBrowser.substring(0, pos) + System.getProperty("user.dir") + aBrowser.substring(pos + 2, aBrowser.length()); for (int pos = aBrowser.length(); (pos = aBrowser.lastIndexOf("%p", pos)) != -1; ) // Substitute the path bit - %p aBrowser = aBrowser.substring(0, pos) + "/docs" + aBrowser.substring(pos + 2, aBrowser.length()); for (int pos = aBrowser.length(); (pos = aBrowser.lastIndexOf("%h", pos)) != -1; ) // Substitute the file name - %h aBrowser = aBrowser.substring(0, pos) + "/index.html" + aBrowser.substring(pos + 2, aBrowser.length()); for (int pos = aBrowser.length(); (pos = aBrowser.lastIndexOf("%f", pos)) != -1; ) // Substitute the full file name - %f aBrowser = aBrowser.substring(0, pos) + aFile + aBrowser.substring(pos + 2, aBrowser.length()); //ERRLN("|" + browser + "|"); args[0] = aBrowser.substring(0, aBrowser.indexOf(' ')); //ERRLN("|" + args[0] + "|"); args[1] = aBrowser.substring(aBrowser.indexOf(' ') + 1, aBrowser.length()); //ERRLN("|" + args[0] + "|" + args[1] + "|"); } else { if (aFile.charAt(4) != ':') aFile = What.appCodeBase.toString() + aFile; } //ERRLN(aFile); try { if (areWe.standAlone) { Runtime rt = Runtime.getRuntime(); rt.exec(args); if (isHelp) OUTLN("Help is on the way."); else OUTLN("Loading display module - " + args[0] + " " + args[1]); What.doRedirect(); } else What.me.getAppletContext().showDocument(new URL(aFile), "Help"); } catch (Exception e) {throw(new SkangException(e.getMessage()));} } /** Does nothing B-). * * @.skang nada data */ public void nothing(String anArgument) { } /** Add the values of all Things to the URL. */ public static String AddThingsToURL(ThingSpace myRoot, String anURL, boolean doHTML) throws SkangException { /* Should figure out why I did the whole :SSL thing in the first place, * then document it. * * In fact, I should carefully document ALL workarounds. */ String post = ""; String protocol = What.appCodeBase.getProtocol(); String host = What.appCodeBase.getHost(); String ssl = ""; boolean isSSL = false; if (anURL.endsWith(":SSL")) { ssl = "&:SSL"; anURL = anURL.substring(0, anURL.length() - 4); isSSL = true; if (protocol.equalsIgnoreCase("http")) protocol = "https"; } else if (anURL.endsWith(":NOSSL")) { ssl = "&:NOSSL"; anURL = anURL.substring(0, anURL.length() - 6); if (protocol.equalsIgnoreCase("https")) protocol = "http"; } if (protocol.equalsIgnoreCase("https")) isSSL = true; int pos = anURL.indexOf("?"); if (pos != -1) { post = anURL.substring(0, pos); for (int i = pos; i < anURL.length(); i++) { if ((i == (anURL.length() - 1)) || (anURL.charAt(i) == '&')) { if (i == (anURL.length() - 1)) i++; String text = anURL.substring(pos, i); //ERRLN("AddThingsToURL() - " + post); int equPos = text.indexOf('='); if (equPos != -1) { String value = URLEncoder.encode(text.substring(equPos + 1)/*, "UTF8"*/); text = text.substring(0, equPos) + "=" + value; } post += text; // if (i < anURL.length()) // post += "&"; pos = i; } } //ERRLN("AddThingsToURL() - " + post); anURL = post; post= ""; } if (sessionID != null) post += "&sessionID=" + URLEncoder.encode(sessionID); // Should probably move this to after the Parameter scan. if (!myRoot.servletToDo.isEmpty()) { post += "&do="; for (Enumeration commands = myRoot.servletToDo.elements(); commands.hasMoreElements();) { String command = (String) commands.nextElement(); if (command != null) post += URLEncoder.encode("\n" + command); } myRoot.servletToDo.removeAllElements(); } //ERRLN("AddThingsToURL() - " + post); // Decide what sort of output is needed. setThing("HTML", doHTML ? "true" : "false"); Enumeration things = Thing.elements(myRoot, Parameter.type); while (things.hasMoreElements()) { Leaf leaf = (Leaf) things.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Parameter) { Thing thing = (Thing) leaf.getValue(); if (thing.fromServer('w', null)) { try { String value = What.me.getThing(thing); // Should not have to do this, something is broken somewhere. if (value == null) value = thing.text; if (value != null) { if (!value.equals("")) { post += "&" + thing.name + "=" + URLEncoder.encode(value); //ERRLN("AddThingsToURL() - " + thing.name + "=" + URLEncoder.encode(value)); } } } catch (SkangException e) { //ERRLN("AddThingsToURL() - " + e.toString() + " " + e.getMessage()); } } } } } post += "&HTML=" + URLEncoder.encode(HTML); if (What.isPHP) { post += "&matrix_rad_page=" + URLEncoder.encode(anURL); anURL = "/D3/matrix_rad.php"; servletPort = ""; servletSSLPort = ""; } if (post.length() > 1) { if (anURL.indexOf("?") == -1) post = anURL + "?" + post.substring(1); else post = anURL + post; } else post = anURL; // Should replace % something with servletPath. if (post.indexOf(":") == -1) { // if (What.appCodeBase.getPort() == -1) // post = What.appCodeBase.getProtocol() + "://" + What.appCodeBase.getHost() + post; // else // post = What.appCodeBase.getProtocol() + "://" + What.appCodeBase.getHost() + ":" + What.appCodeBase.getPort() + post; if (isSSL) { if ((servletSSLPort == null) || (servletSSLPort.equals(""))) post = protocol + "://" + host + post; else post = protocol + "://" + host + ":" + servletSSLPort + post; } else { if ((servletPort == null) || (servletPort.equals(""))) post = protocol + "://" + host + post; else post = protocol + "://" + host + ":" + servletPort + post; } } ERRLN("AddThingsToURL() - " + post + ssl); return post + ssl; } /** POST the values of all Things to the URL, show the returned content. * * @.skang postshow URL,name */ public void postShowThings(ThingSpace myRoot, String anURL, String aTarget) throws SkangException { anURL = AddThingsToURL(myRoot, anURL, true); anURL = anURL.replace('\\', '/'); // For hard coded slashes. try {this.getAppletContext().showDocument(new URL(anURL), aTarget);} catch (Exception e) {throw(new SkangException(e.getMessage()));} } /** POST the values of all Things to the URL, return the content. * * @.skang post URL */ public static String postThings(ThingSpace myRoot, String anURL) throws SkangException { String results = ""; BufferedReader in = new BufferedReader(new InputStreamReader(new BufferedInputStream(What.me.openFile(AddThingsToURL(myRoot, anURL, false))))); String text; try { while ((text = in.readLine()) != null) results += text + "\n"; } catch (Exception e) {;} ERRLN(" "); return results; } /** POST the values of all Things to the URL, parse the returned content. * * @.skang postparse URL */ public String postParseThings(ThingSpace myRoot, String anURL) throws SkangException { String results = null; //showCommands = true; results = skangRead(myRoot, AddThingsToURL(myRoot, anURL, false)); //showCommands = false; OUTLN(" "); ERRLN(" "); return results; } /** Output errors and warnings only. * * @.skang quiet * @.shortcut q */ public void quiet() { debug = -1; } /** Remove an existing thing. * * @.skang remove name */ public void removeThing(ThingSpace myRoot, String aName) throws SkangException { Thing thing = (Thing) Thing.get(myRoot, aName); thing.myRoot.get(thing.type.toUpperCase()).up().pluck(aName); thing.myRoot.pluck(aName.replace('.', '_')); System.runFinalization(); System.gc(); } /** Change the help for something. * * @.skang sethelp name,data */ public void setHelp(ThingSpace myRoot, String aName, String aHelp) throws ThingNotFoundException { Thing.get(myRoot, aName).setHelp(aHelp); } /** Set the current value of an existing Thing. * * @.skang set name,data */ public static void setThing(String aName, String aValue) //throws SkangException { //ERRLN("setThing(" + aName + ", " + aValue + ")"); // Should actuall throw the exception, too lazy right now cause it is called from all over. try {Thing.setText(aName, aValue);} catch (Exception e) {ERRLN("\nERROR - setThing(" + aName + ", " + aValue + ") " + e.toString() + " " + e.getMessage() + "\n");} // return(Thing.setText(aName, aValue)); } /** Parse the contents of a skang file or URL. * * @.skang skang URL */ public String skangRead(ThingSpace myRoot) throws SkangException { //ERRLN("skangRead()"); // Replacing with '/' cause '\' from windows escapes stuff in the parser. String name = null; if (What.me.skinURL != null) name = What.me.skinURL.replace('\\', '/'); else if (this.skinURL != null) name = this.skinURL.replace('\\', '/'); return skangRead(myRoot, name); } public String skangRead(ThingSpace myRoot, String aSkin) throws SkangException { //ERRLN("skangRead(" + aSkin + ")"); String result = null; if (aSkin == null) aSkin = What.me.getClass().getName().replace('.', What.separator) + ".skang"; if (aSkin.equals("")) return result; boolean post = (aSkin.indexOf("?") != -1); if (!post) { ERRLN("Loading skin - " + aSkin); What.doRedirect(); } // Grab skinURL and parse it. if (post) { result = this.parseTheSkang(myRoot, new InputStreamReader(new BufferedInputStream(What.me.openFile(aSkin))) ); ERRLN(" "); What.doRedirect(); } else result = this.parseTheSkang(myRoot, new InputStreamReader(new BufferedInputStream(What.me.openResource(aSkin))) ); if (!What.isSplashing) { try { // Call initGUI() here rather than in Module.java because initGUI() is supposed to be called after the skins are done. Enumeration modules = Thing.elements(myRoot, Module.type); while (modules.hasMoreElements()) { Leaf leaf = (Leaf) modules.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Module) { Module thing = (Module) leaf.getValue(); Skang module = thing.module; if (module != null) if (!module.initGUIDone) module.initGUI(); // Do everybodies initGUI(). } } } } catch (Exception e) {ERRLN("skang().skangRead(" + aSkin + ") " + e.toString() + " " + e.getMessage());} } if (!post) { ERRLN(" "); What.doRedirect(); } What.me.setVisible(true); What.findStatus(); What.redirectAndWhinge(); // Buggered if I know, the docs are not clear, so the browsers all do it different. What.me.invalidate(); What.me.validate(); What.me.repaint(); if (!post) { ERRLN(""); What.doRedirect(); } What.isSplashing = false; //ERRLN("skangRead(" + aSkin + ") - END"); return result; } /** Quit, exit, remove thyself. * * @.skang quit */ public void startQuit() { //ERRLN("->Skang.startQuit()"); areWe.quitting = true; } /** Clear all messages. * * @.skang stopwhinging */ public void stopWhinging(ThingSpace myRoot) { Whinge whinge = myRoot.whinge; if (whinge != null) whinge.stopWhinging(); } /** Returns details of an existing Thing. * * @.skang tell name */ public String tellThing(ThingSpace myRoot, String aName) throws SkangException { // With no name, should return every tell string. return(((Thing) Thing.get(myRoot, aName)).tell); } /** Toggle ignorance of a certain browser bug. * * @.skang togglebug */ public static void toggleIgnoreBrowserBug() { ignoreBrowserBug = !ignoreBrowserBug; } /** Output advanced information. * * @.skang verbose * @.shortcut v */ public static void verbose() { debug = 1; } //********************************************************************** /** URL of skin file. * * @.skangarg skinURL * @.required * @.shortcut s * @.secure RI- */ public String skinURL = null; /** Debugging level. * * @.skangarg debug * @.default "0" * @.help Set debugging level to :\n\t-1 - errors and warnings only (-q)\n\t0 - basic information\n\t1 - advanced information (-v)\n\t2 - trace functions\n\t3 - trace protocol\n\t4 - dump packets + stuff\n\t5 - detail */ public static short debug = 0; /** Browser to run. * * @.skangarg browser * @.default "mozilla %f" */ public static String browser = null; /** Download directory. * * @.skangarg downloaddir * @.default "download" */ public static String downloadDir = null; /** SessionID from servlet. * * @.skangarg sessionID */ public static String sessionID = null; /** JSESSIONID from servlet engine. * * @.skangarg JSESSIONID */ public static String JSESSIONID = null; /** Servlet path. * * @.skangarg servletpath * @.default "matrix_rad" */ public static String servletPath = null; /** Servlet port. * * @.skangarg servletport */ public static String servletPort = ""; /** Servlet SSL port. * * @.skangarg servletsslport */ public static String servletSSLPort = ""; /** Output to HTML? * * @.skangarg HTML * @.default "false" */ public static String HTML = "false"; /** Output though the PHP wrapper * * @.skangarg PHP * @.default "false" */ public static String PHP = "false"; /** Run in browser window? * * @.skangarg inbrowser * @.default "true" */ public static String inBrowser = "true"; /** Dummy to avoid a web server bug. * * @.skangarg SSL */ public static String SSL = null; /** Dummy to avoid a web server bug. * * @.skangarg NOSSL */ public static String NOSSL = null; /** Are we doing corporate shit? * * @.skangarg corporate */ public static String corporate = "get real"; protected boolean initGUIDone = false; private boolean showCommands = false; public short currentState = IDLE; private Thread m_Skang = null; // The applets thread. public SkangletBase skanglet = null; public Module me = null; // public Who user = null; public static What areWe = new What(); public static boolean isGnome = true; // Lets be optomist, to start with at least B-). public static boolean ignoreBrowserBug = true; private static short counter = 0; private static short nextCopyright = 0;; public static String arguments[] = null; protected String modules = null; public static Fascist security = null; public static final String defaultStuff = null; }