    var isFirstInit = true; // initial synchro
    var executingCommand = false; // synchro, do not run twice at a time
    var closingAll = false; // synchro, closing all windows
  	var stopDaemon = false; // stop daemon
    
    var retry_count = 20; // reexecute command retry_count times if not succesful
    var retry_delay = 500; // delay between reexecutions
    
    var commandMode = "script"; // command mode, "applet"/"script", now always "script"
    
    function init() {
      if(commandMode == "script") {
        col_init(); // init the 'collection' support functions
        startDaemon(); // start reading and executing commands from applet
      }
    }

    function startDaemon() {
      stopDaemon = false;
      daemon();
    }
    
    // restart daemon after delay
    function runDaemon() {
      if(!stopDaemon)
        setTimeout("daemon()", 250);
    }
    
    function stopDaemon() {
      stopDaemon = true;
    }
    
    function daemon() {
      var cmd;
      if(!executingCommand) { // synchro
        executingCommand = true;
        var applet = document.applets["sticky"];
        if(applet != null && applet.isActive()) { // applet must be started
          if(isFirstInit) {
            isFirstInit = false;
            applet.setProperty("cobrowsing-commandMode", commandMode); // initial synchro
          }
          var s = applet.getProperty("cobrowsing-commandReady"); // check if there is command ready on the applet
          if(s == "true") {
            applet.setProperty("cobrowsing-commandReady", "false"); // synchro, reset flag            
            cmd = applet.getProperty("cobrowsing-command"); // read command
            if(cmd != null)
              executeCommand(cmd); // execute command
            applet.setProperty("cobrowsing-readyForNextCommand", "true"); // synchro, reset flag
          }
        }
        executingCommand = false;
      }
      // re-run daemon after delay
      runDaemon();
    }
    
    // dispatch command
    function executeCommand(cmd) {
      cmd += " " + retry_count;
      var cmdArr = String(cmd).split(" ");
      if(cmdArr[0] == "OPEN") {
        cmdOpen(cmd);
      } else if(cmdArr[0] == "SHOW") {
        cmdShow(cmd);
      } else if(cmdArr[0] == "END") {
        cmdCloseAll(cmd);
      }
    }
    
    // open new window
    function cmdOpen(cmd) {
      if(!closingAll) { // if not closing all windows
        var cmdArr = String(cmd).split(" ");
        if(col_find(cmdArr[1]) == -1) {  // window does not exist yet
          // open the window          
          var w = window.open(cmdArr[2], cmdArr[1], "status=yes,resizable=yes,toolbar=no,menubar=yes,location=no");
          // store the window object, use its name as key
          col_add(cmdArr[1], w);
        } else {
          // window with that name exists already, use Show command
          cmdArr[3] = cmdArr[2];
          cmdArr[2] = "_top";
          cmdShow(create_cmd(cmdArr));
        }
      } else {
        // try later
        setTimeout("cmdOpen(\""+ cmd +"\")", retry_delay);
      }      
    }
    
    function cmdShow(cmd) {
      if(!closingAll) { // if not closing all windows
        var cmdArr = String(cmd).split(" ");
        var w = col_get(cmdArr[1]); // get the window object by its name
        if((w != null) && (!w.closed)) { // window not found or closed
          if(containsFrame(w, cmdArr[2])) { // if the target frame exists load the url
            w.open(cmdArr[3], cmdArr[2]);
          } else { // else try again later 
            retries = cmdArr[4];
            if(retries > 0) {
              cmdArr[4]--;
              setTimeout("cmdShow(\""+ create_cmd(cmdArr) +"\")", retry_delay);
            }
          }
        } else {
          col_remove(cmdArr[1]);
        }
      } else {
        // try later
        setTimeout("cmdShow(\""+ cmd +"\")", retry_delay);
      }      

    }
    
    // close all windows
    function cmdCloseAll(cmd) {
      closingAll = true; // synchro
      
      var cmdArr = String(cmd).split(" ");
      var w, arr, i;
      arr = col_values;
      for (i in arr) { // each window
        w = arr[i];
        if(w != null) {
          if(!w.closed)
            w.close();
        }
      }
      col_init();
      
      closingAll = false;
    }
    
    function containsFrame(f, fname) { // does the target frame exist ?
      if(typeof(f.frames[fname]) != "undefined") { // it exists
        return true;
      } else { // else go deeper
        var i;
        for(i = 0; i < f.frames.length; i++) // recursion through all child frames
          if(containsFrame(f.frames[i],fname))
            return true;
        return false;
      }
    }
    
    // assemble string command
    function create_cmd(arr) {
      var i, cmd = "";
      for(i = 0; i < arr.length; i++) {
        if(i > 0)
          cmd += " ";
        cmd += arr[i];
      }
      return cmd;
    }
    
    // collection implementation
    var col_keys;
    var col_values;
    var col_count;
    
    function col_init() {
      col_keys = new Array();
      col_values = new Array();
      col_count = 0;
    }
    
    function col_add(key, val) {
      var p = col_find(key);
      if(p >= 0) {
        col_values[p] = val;
      } else {
        col_keys[col_count] = key;
        col_values[col_count] = val;
        col_count++;
      } 
    }
    
    function col_remove(key) {
      var p = col_find(key);
      if(p >= 0) {
        var i;
        for(i = p; i < col_count-1; i++) {
          col_keys[i] = col_keys[i+1];
          col_values[i] = col_values[i+1];
        }
        col_count--;
      }
    }
    
    function col_get(key) {
      var p = col_find(key);
      if(p >= 0) {
        return col_values[p];
      }     
      return null;
    }
    
    function col_find(key) {
      var i;
      for(i = 0; i < col_count; i++) {
        if(col_keys[i] == key)
          return i;
      }
      return -1;
    }

