/*
 * Scone - The Web Enhancement Framework
 * Copyright (C) 2009 Harald Weinreich, Volkert Buchmann, Frank Wollenweber, Torsten Haß
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 package scone.accesstracking2;


import java.util.Date;
import java.util.Properties;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.net.InetAddress;
import java.net.SocketException;

import scone.netobjects.NetNode;
import scone.netobjects.NetNodeCache;
import scone.netobjects.UserCache;

import com.ibm.wbi.RequestEvent;
import com.ibm.wbi.RequestRejectedException;
import com.ibm.wbi.protocol.http.DocumentInfo;
import com.ibm.wbi.protocol.http.HttpGenerator;
import com.ibm.wbi.protocol.http.HttpRequest;
import com.ibm.wbi.protocol.http.HttpResponse;
import com.ibm.wbi.protocol.http.beans.FileGenerator;
import com.ibm.wbi.protocol.http.beans.FormHelper;
import com.ibm.wbi.protocol.http.beans.StaticHtmlGenerator;


/**
 * This meg creates the user logging entries in the access database.<P>
 * If the user is unknown (no cookie ID to the host tracking.scone.de is set)
 * a login screen is displayed<P>
 * After the login, a cookie is set and from now on the userId from this cookie is used.<P>\n
 * The meg is called when
 * <OL>
 * <LI> a transfer is startet (filename = _start)
 * <LI> the page was loaded (filename = _load)
 * <LI> the page was left (filename = _stop)
 * </OL>\n
 * The correcconding JavaScript-Code is inserted by the JavaScriptAdder.<BR>
 * The JS-methods stop() and loaded() calls are inserted by the BodyEventAdder.<BR>
 * onClick-events to all Links can be added by activating the LinkEventAdder.
 * <P>
 * To access the Scone parameters in your JavaScript-Code please use the following variables:<OL>
 * <LI>Scone_Parent_Name is the name of parent frame
 * <LI>Scone_Parent_Location is the URI of the parent frame
 * <LI>Scone_UserID is the current User ID
 * </OL>
 *
 * @author Harald Weinreich
 * @version 1.3, 11/21/2004
 */
public class AccessTrackingMeg extends HttpGenerator {

    private DocumentInfo documentInfo;
    private String       file;
    private Properties   formParameter;
    private HttpRequest  request;
    private HttpResponse response;
    private String       id;            // userid as string
    private long         userId;        // userid as integer
    private String       nodeId = "";   // NodeId of the current object.
    private String       nodeURI = "";  // NodeId of the current object.
    private String       browser = "";  // The name of the browser...
    private String       query   = "";  // NodeId of the current object.
    private String       fragment = ""; // NodeId of the current object.
    private long         start = 0L;    // Start time of visit to page
    private String       frame = "";    // Name of this frame
    private String       parentNodeId = "";     // nodeId of parent frame
    private String       parentFrame = "";      // Name of parent frame
    private String       referrerNodeId = "";   // NodeId of the referrer
    private int          action = 0;            // Action of the event.
    private int          history = 0;           // Length of Browser-History
    private String       event = "";            // These events exist: start, load, stop
    private String       clientInetAddress = "";      // String of IP-Address of browser...
    private EventDecoder eventDecoder;          // The Eventdecoder to decode the users browsing actions...

    public void handleRequest(RequestEvent e) throws RequestRejectedException {

        documentInfo = (DocumentInfo) e.getRequestInfo(); // get RequestInfo
        file = documentInfo.getPath();           // get Path+File of the URL

        request = new HttpRequest(e, true);    // Get the request header
        id = request.getCookie("ID");          // Get Cookie "ID"

        byte [] caddr1 = documentInfo.getClientAddress().getAddress();
        long caddr2 = 0;
        for (int i = 0; i < caddr1.length; i++ )
            caddr2 = (caddr2 * 1000) + caddr1[i];
        clientInetAddress = String.valueOf(caddr2);

        if (AccessTracking.props.get("Disable user handling").equals("true")) {
            id = clientInetAddress;
        }  // User tracking disabled: UserID is IP Address of user...

        // test if the cookie contains a valid UserID
        try {
            if (id != null) {
                userId = Long.parseLong(id);
            }
        } catch (NumberFormatException ex) {
            System.err.println("Error: Cookie ID is no number");
            userId = 0L;
            id = null;
        }

        HttpGenerator g = null;

        // default browsing, transfer of page starts: file="_id"., return Javascript for tracking or Login-Screen...
        if (file.startsWith("/_id")) {
            // Verify id (and userId).
            if ( id == null || (!id.equals("0") && UserCache.checkById(id) == null) )  // No Cookie or user not known. Redirecting to new user screen...
            {
                StaticHtmlGenerator sg = new StaticHtmlGenerator(); // Return generated document to the client
                String jsCode = "function _scone_loaded() { window.location.href='http://users.scone.de/'; }\n";                      // Dummy functions

                jsCode += "function _scone_stop() {}\n";
                // jsCode += "setTimeout(\"window.location.href='http://users.scone.de/' \",500);";   //Redirect URL with timeout to avoid errors in IE4
                // jsCode += "window.location.href='http://users.scone.de/';";   //Redirect URL with timeout to avoid errors in IE
                sg.setStaticHtml(jsCode);
                sg.setContentType("application/x-javascript");      // Set type to javascript
                g = sg;                                               // Return Generator
                // System.out.println(jsCode);
                if (id == null) {
                    System.out.println("No user Cookie found for .scone.de -> redirecting browser to user tracking screen");
                } else {
                    System.out.println("User Id " + id + " unknown -> redirecting browser to user tracking screen");
                }
            }
            else // User known
            {
                // Create nodeIdString from filename
                String nodeId = file.substring(4); // "/_id".length() is 4

                if (nodeId == null || nodeId.length() == 0) {
                    nodeId = "";
                }   // was it available?

                // Return JavaScript code to log user actions...
                StaticHtmlGenerator sg = new StaticHtmlGenerator(); // Return generated document to the client
                String jsCode = "";

                jsCode += "var Scone_Parent_Name='';\n";        // Name of parent frame
                jsCode += "var Scone_Parent_Location='';\n";    // URI of parent frame
                jsCode += "var Scone_UserID='"+id+"';\n";             // User ID
                jsCode += "var Scone_NodeID='"+nodeId+"';\n";             // Node ID
                jsCode += "var _scone_parent_location='';\n";
                jsCode += "var _scone_parent_name='';\n";
                jsCode += "var _scone_history_length=0;\n";
                jsCode += "var _scone_referrer='';\n";
                jsCode += "var _scone_stop_event_sent='0';\n";
                jsCode += "var _scone_link='';\n";
                jsCode += "var _scone_link_type='';\n";
                jsCode += "var _scone_window_size='';\n";
                jsCode += "var _scone_click_position='';\n";
                jsCode += "var _scone_fragment='';\n";
                jsCode += "var _scone_form='';\n";
                jsCode += "var _scone_load_event_sent=0;\n";
                jsCode += "var _scone_load_time=0;\n";
                jsCode += "var _scone_stop_event_sent=0;\n";
                jsCode += "var _scone_stop_timeout=\"\";\n";
                
                jsCode += "var _user_agent=navigator.userAgent.toLowerCase();\n";
                jsCode += "var _is_gecko=(_user_agent.indexOf('gecko') != -1);\n";
                jsCode += "var _is_ie4up=(_user_agent.indexOf('msie') != -1 && _user_agent.indexOf('opera') == -1 &&  parseInt(navigator.appVersion) >= 4);\n";
                jsCode += "var _scone_browser=''; ";
                jsCode += "if (_is_gecko) _scone_browser='&browser=gecko'; ";
                jsCode += "if (_is_ie4up) _scone_browser='&browser=msie';\n";
                //jsCode += "alert(_scone_browser);\n";

                jsCode += "_scone_a" + nodeId + " = new Image();\n";
                jsCode += "_scone_b" + nodeId + " = new Image();\n";
                jsCode += "_scone_c" + nodeId + " = new Image(); _scone_c"+ nodeId + ".src == ''; \n";
                jsCode += "_scone_d" + nodeId + " = new Image();\n\n";


                jsCode += "try { \n";  // 
                jsCode += "  if (history.length && _scone_history_length==0) {_scone_history_length=history.length;}\n";
                jsCode += "} catch (exception) { \n // \n";  // TRY-CATCH!
                //jsCode += "  if (exception.description == null) { alert(\"Exception: \" + exception.message); }\n";
                //jsCode += "  else { alert(\"Exception: \" + exception.description); }\n";
                jsCode += "}\n\n";
                
                jsCode += "try { \n";  // TRY-CATCH-Code: The access to some objects may be forbidden...
                jsCode += "  if (window.location!=window.parent.location || window.location!=window.top.location || parent.frames.length>0) _scone_parent_location='&parentUri='+escape(window.parent.location); \n";
                jsCode += "} catch (exception) { \n // \n";  // TRY-CATCH!
                // use the referrer to get the parent url if these are cross site frames...
                jsCode += "  _scone_parent_location='&parentUri='+escape(document.referrer);\n";
                //jsCode += "  if (exception.description == null) { alert(\"Exception: \" + exception.message); }\n";
                //jsCode += "  else { alert(\"Exception: \" + exception.description); }\n";
                jsCode += "}\n\n";

                jsCode += "\ntry { \n";  // TRY-CATCH-Code: The access to some objects may be forbidden...
                // jsCode += "  if (window.location==window.parent.location) window.parent.name=window.name;\n";
                jsCode += "  if (window.name!=window.parent.name) _scone_parent_name='&parent='+escape(window.parent.name);\n";
                jsCode += "  if (window.name!=window.parent.name) {Scone_Parent_Name=parent.top.name; Scone_Parent_Location=parent.top.location.href;}\n";
                jsCode += "} catch (exception) { \n // \n";  // TRY-CATCH!
                jsCode += "  _scone_parent_name='&parent=PARENT_FRAME_ACCESS_DENIED';\n";
                //jsCode += "  if (exception.description == null) { alert(\"Exception: \" + exception.message); }\n";
                //jsCode += "  else { alert(\"Exception: \" + exception.description); }\n";
                jsCode += "}\n\n";
                
                jsCode += "_scone_set_window_name();\n";

                // jsCode += "for(var i=0; i < parent.frames.length; i++) alert(parent.frames[i].name);";
                // jsCode += "alert(window.parent.location); ";
                // jsCode += "alert(window.outerHeight + \" -- \" + top.name); ";

                // Generate imagenames and filenames from nodeId. Otherwise problems with frames (pictures loaded only once.)
                // These lines could _theoretically_ be shorter, but there are problems with JavaScript...
                jsCode += "_scone_a"
                        + nodeId + ".src = 'http://tracking.scone.de/_start"
                        + nodeId
                        + "?start='+_scone_start_time+'&frame='+escape(window.name)+_scone_browser+_scone_parent_name+_scone_referrer+_scone_parent_location+'&history='+_scone_history_length+'&postData='+escape(_scone_postData); \n\n";

                jsCode += "function _scone_set_window_name() { \n";
                jsCode += "  try { \n";  // TRY-CATCH-Code: The access to some objects may be forbidden...
                jsCode += "    if ((!window.name) || (window.name=='_blank')) {\n"; // || (window.location==window.parent.location && window.name.indexOf('SCONE')==-1) ) {\n"; 
                // jsCode += "      if (_scone_window_name.indexOf('SCONE') == -1) {window.name = 'SCONE'+_scone_start_time+Math.floor(Math.random()*10000); _scone_referrer='&referrer=[New%20Window]';}\n"; // Problems with some Spiegel-Online pages that check the name of the page...
                //jsCode += "      else {window.name = _scone_window_name;}\n";
                jsCode += "      window.name = 'SCONE'+_scone_start_time+Math.floor(Math.random()*10000); _scone_referrer='&referrer=[New%20Window]';\n";
                jsCode += "    } else if(document.referrer) _scone_referrer='&referrer='+escape(document.referrer);\n";
                jsCode += "  } catch (exception) {\n";  // TRY-CATCH!
                jsCode += "    //\n";
                jsCode += "  }\n";
                jsCode += "}\n";


                // Function to be called after page was loaded ---------------------------
                jsCode += "function _scone_loaded() {\n";
                jsCode += "  if (_scone_load_event_sent == 0) {\n";     // Only send once!
                jsCode += "     _scone_load_event_sent = 1;\n";
                jsCode += "  	_scone_set_window_name();\n";
                jsCode += "  	_scone_load_time=(new Date).getTime();\n";
                // Only send Message to AccesstrackingMeg if needed...
                if (AccessTracking.props.get("Create extra event after page is loaded").equals("true"))
                	jsCode += "  	_scone_b"
                	          + nodeId + ".src = 'http://tracking.scone.de/_loaded"
                              + nodeId 
                              + "?start='+_scone_start_time+'&load='+_scone_load_time+'&frame='+escape(window.name)+_scone_browser+_scone_parent_name+_scone_referrer+_scone_parent_location+'&history='+_scone_history_length; \n";
                
                jsCode += "  }\n";
                // jsCode += "  setTimeout(\"window.status='xxx';\",1000);\n"; // DOES NOT HELP - the transferring data... is a bug in Gecko :-(
                jsCode += "}\n";

                // Function to ba called when a user leaves a page ------------------------------------
                jsCode += "function _scone_stop() {\n";
                jsCode += "  _scone_set_window_name();\n";
                jsCode += "  if (_scone_stop_event_sent == 0) {\n";     // Only send once, as onBeforeUnload may als be called...
                jsCode += "    _scone_stop_event_sent = 1;\n";
                jsCode += "    _scone_stop_time=(new Date).getTime();\n";
                jsCode += "    _scone_c" + nodeId + ".src = 'http://tracking.scone.de/_stop"
                        + nodeId
                        + "?start='+_scone_start_time+'&load='+_scone_load_time+'&stop='+_scone_stop_time+'&frame='+escape(window.name)+_scone_browser+_scone_parent_name+_scone_referrer+_scone_parent_location+'&history='+_scone_history_length+_scone_link+_scone_link_type+_scone_form+'&size='+_scone_window_size+'&clickPos='+_scone_click_position; \n";
                // jsCode += "  while( _scone_c"+ nodeId + ".readyState != \"complete\") { } ;\n"; // Buggy, doesn't work
                // jsCode += "  for(i=1;i<400000;i++); \n";    // Somehow crap but works...
                //jsCode += "  while( _scone_c"+ nodeId + ".complete == false) { \n";
                // jsCode += "  for(i=1;i<400000;i++); \n";    // Somehow crap but works...
                // jsCode += "    alert( '-'+_scone_c"+ nodeId + ".readyState+'-' );\n";
                //jsCode += "  }\n";
                //jsCode += "  alert( _scone_c"+ nodeId + ".src );\n";
                jsCode += "  var _timeout = 400;\n";
                jsCode += "  if (top.frames.length>0) _timeout = _timeout / top.frames.length;\n";
                jsCode += "   while( _scone_stop_time + _timeout >= (new Date).getTime() ) {} ;\n";  // Wait 400ms - Also crap but works...
                jsCode += "  _scone_link='';\n";
                jsCode += "  _scone_link_type='';\n";
                jsCode += "  _scone_form='';\n";
                jsCode += "  if (_scone_stop_timeout) window.clearTimout(_scone_stop_timeout);";
                jsCode += "  }\n";
                jsCode += "}\n";

           
                // Set LinkID when a user clicks a link...
                jsCode += "function _scone_setlink(e,l,f,t) {\n";  // l is the linkID, f is the fragment, t is the type
                jsCode += "  _scone_set_window_name();\n";
                jsCode += "  try { \n";  // TRY-CATCH-Code: The access to some objects may be forbidden...
                jsCode += "  	_scone_window_size = window.top.document.body.clientWidth+'x'+window.top.document.body.clientHeight;";
                jsCode += "  	_scone_cx = (_is_gecko) ? e.clientX + window.scrollX : window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;";
                jsCode += "  	_scone_cy = (_is_gecko) ? e.clientY + window.scrollY : window.event.clientY + document.documentElement.scrollTop  + document.body.scrollTop;";
                jsCode += "  	_scone_click_position = _scone_cx+'x'+_scone_cy;";
                jsCode += "  } catch (exception) {\n";  // TRY-CATCH!
                jsCode += "    //\n";
                jsCode += "  }\n";
                //jsCode += " alert(_scone_window_size);";
                //jsCode += " alert(_scone_click_position);";
                jsCode += "  _scone_link='&linkId='+l;\n";
                jsCode += "  _scone_link_type='&linkType='+t;\n";
                jsCode += "  _scone_stop_event_sent = 0;\n";
                jsCode += "  _scone_stop();\n";   // call Stop event...
                // jsCode += "  setTimeout(\"_scone_stop_event_sent = 0;\",1000);\n"; // Allow new stop events after 1 sec
                jsCode += "  if (f != '') {\n";     // Fragment is only set for links on that page...
                jsCode += "    _scone_stop_timeout = setTimeout(\"_scone_stop_event_sent = 0;\",3000);\n"; // Allow new stop events after 3 sec
                jsCode += "    _scone_fragment='&fragment='+f;\n";
                jsCode += "    _scone_history_length++;\n";     // Increase history manually!
                jsCode += "    _scone_link_time=(new Date).getTime();\n";
                jsCode += "    _scone_d"
                          + nodeId + ".src = 'http://tracking.scone.de/_link"
                          + nodeId
                          + "?start='+_scone_start_time+'&link='+_scone_link_time+'&frame='+escape(window.name)+_scone_browser+_scone_parent_name+_scone_referrer+_scone_parent_location+'&history='+_scone_history_length+_scone_link+_scone_link_type+_scone_fragment+'&size='+_scone_window_size+'&clickPos='+_scone_click_position;\n";
                jsCode += "  _scone_link='';\n";
                jsCode += "  _scone_link_type='';\n";
                jsCode += "  _scone_start_time=(new Date).getTime();\n";
                jsCode += "  }\n";
                jsCode += "}\n";

                // Set formAction when a user clicks submit
                jsCode += "function _scone_setform(a) { \n";
                jsCode += "  _scone_stop_event_sent = 0;\n";
                jsCode += "  _scone_form='&formAction='+escape(a);\n"; 
                jsCode += "}\n";

                // System.out.println(jsCode);
                
                sg.setStaticHtml(jsCode);                           // Set dummy text
                sg.setContentType("application/x-javascript");      // Set type to javascript
                g = sg;                                               // Return Generator
            }

        } 
        else // These are the events... ---------------------------------------------------------
        {
            formParameter = FormHelper.interpretFormData(e);  // get Query Parameter from URL
            if (formParameter == null) { // Sometimes WBI does not return valid Properties, especially if the transfer was interrupted...
                System.out.println("Error!!!----------------------------------------------------------------------");
                formParameter = new Properties();
            }

            // A new page is being loaded... ----------------------------------------------------
            if (file.startsWith("/_start")) 
            {
                event = "start";
                getAccessKey("/_start");

                parseBrowserData();

                // Did the user click a submit button?
                String postData = formParameter.getProperty("postData");
                if (postData == null) {
                    postData = "";
                }                               // was it available?
                // System.out.println("postData = " + postData);

                if (browser.equals("gecko"))
                    eventDecoder = new EventDecoderGecko();        // decodes received data and creates Events
                else if (browser.equals("msie"))
                    eventDecoder = new EventDecoderIE();        // decodes received data and creates Events
                else 
                    eventDecoder = new EventDecoder();        // decodes received data and creates Events

                eventDecoder.startEvent(id, nodeId, start, frame,
                                        fragment, query, postData,                    // Fragment, query, post
                                        referrerNodeId,
                                        parentFrame,
                                        parentNodeId,
										"","",
                                        history );
    
                // return dummy line
                FileGenerator rg = new FileGenerator("resources/scone/proxy/pixel.gif", "image/gif");
                g = rg;

            } 
            // Page load finished -------------------------------------------------------------
            else if (file.startsWith("/_loaded"))     // JS-Event if page was loaded
            {
                event = "loaded";
                getAccessKey("/_loaded");
    
                parseBrowserData();

                // get load time
                String loadString = formParameter.getProperty("load");
    
                if (loadString == null) {
                    loadString = "0";
                }
                long load = Long.parseLong(loadString);            // Convert to long
                // Date longDate = new Date(long); System.out.println(longDate);

                long loadTime = load - start;

                if (browser.equals("gecko"))
                    eventDecoder = new EventDecoderGecko();        // decodes received data and creates Events
                else if (browser.equals("msie"))
                    eventDecoder = new EventDecoderIE();        // decodes received data and creates Events
                else 
                    eventDecoder = new EventDecoder();        // decodes received data and creates Events

                eventDecoder.loadEvent( id, nodeId, start, frame,
                                        referrerNodeId,
                                        parentFrame,
                                        parentNodeId,
                                        loadTime );
    
                // Return dummy line.
                FileGenerator rg = new FileGenerator("resources/scone/proxy/pixel.gif", "image/gif");
                g = rg;

                // System.out.println("loadTime = " + loadTime+"ms");

            } 
            // User left the page. ---------------------------------------------------------------------------------
            // We are using onbeforeunload -> Only works in IE5ff or Mozilla 1.7 ff or Firefox 0.9ff
            else if (file.startsWith("/_stop")) 
            {
                event = "stop";
                getAccessKey("/_stop");

                parseBrowserData();

                // get stop time
                String stopString = formParameter.getProperty("stop");
    
                if (stopString == null) {
                    stopString = "0";
                }
                long stop = Long.parseLong(stopString);            // Convert to long
                // Date longDate = new Date(long); System.out.println(longDate);
                long stayTime = stop - start;

                // get load time
                String loadString = formParameter.getProperty("load");
                if (loadString == null) {
                    loadString = "0";
                }
                long load = Long.parseLong(loadString);            // Convert to long
                long loadTime = (load > 0)?load-start:0;
                //System.out.println("LOADinSTOP:"+loadTime);
                
                // Which link did the user click?
                String linkId = formParameter.getProperty("linkId");
                if (linkId == null) {
                    linkId = "0";
                }                               // was it available?

                // get the link type
                String linkTypeString = formParameter.getProperty("linkType");
                if (linkTypeString == null) {
                    linkTypeString = "0";
                }
                int linkType = Integer.parseInt(linkTypeString);            // Convert to int

                // What was the window size?
                String windowSize = formParameter.getProperty("size");
                if (windowSize == null) {
                	windowSize = "";
                }                               // was it available?

                // What was the position of the link?
                String clickPos = formParameter.getProperty("clickPos");
                if (clickPos  == null) {
                	clickPos = "";
                }
                
                // Did the user click a submit button?
                String formAction = formParameter.getProperty("formAction");
                if (formAction == null) {
                    formAction = "";
                }                               // was it available?
                
                if (browser.equals("gecko"))
                    eventDecoder = new EventDecoderGecko();        // decodes received data and creates Events
                else if (browser.equals("msie"))
                    eventDecoder = new EventDecoderIE();        // decodes received data and creates Events
                else 
                    eventDecoder = new EventDecoder();        // decodes received data and creates Events

                eventDecoder.stopEvent( id, nodeId, start, frame,
                                        referrerNodeId,
                                        parentFrame,
                                        parentNodeId,
                                        stayTime,
                                        loadTime,
                                        linkId,
                                        linkType,
										windowSize,
										clickPos,
                                        formAction );

                FileGenerator rg = new FileGenerator("resources/scone/proxy/pixel.gif", "image/gif");
                g = rg;
                
                // Debuggin data
                //System.out.println("STOPP!!!!!!!!!!!!!!!!1");
                //System.out.println("linkId = " + linkId);
                //System.out.println("formAction = " + formAction);
                //System.out.println("LinkType: " + Integer.toBinaryString(linkType));

            }
            // User clicked a link. ---------------------------------------------------------------------------------
            else if (file.startsWith("/_link")) 
            {
                event = "link";
                getAccessKey("/_link");

                parseBrowserData();

                // get load time
                String linkString = formParameter.getProperty("link");
                if (linkString == null) {
                    linkString = "0";
                }
                long link = Long.parseLong(linkString);            // Convert to long

                long linkTime = link - start;
    
                // Which link did the user click?
                String linkId = formParameter.getProperty("linkId");
                if (linkId == null) {
                    linkId = "";
                }                               // was it available?

                // Which link did the user click?
                fragment = formParameter.getProperty("fragment");
                if (fragment == null) {
                    fragment = "";
                }                               // was it available?

                // get the link type
                String linkTypeString = formParameter.getProperty("linkType");
                if (linkTypeString == null) {
                    linkTypeString = "0";
                }
                long linkType = Long.parseLong(linkTypeString);            // Convert to long

                // What was the window size?
                String windowSize = formParameter.getProperty("size");
                if (windowSize == null) {
                	windowSize = "";
                }                               // was it available?

                // What was the position of the link?
                String clickPos = formParameter.getProperty("clickPos");
                if (clickPos  == null) {
                	clickPos = "";
                }                               // was it available?
                
                if (browser.equals("gecko"))
                    eventDecoder = new EventDecoderGecko();        // decodes received data and creates Events
                else if (browser.equals("msie"))
                    eventDecoder = new EventDecoderIE();        // decodes received data and creates Events
                else 
                    eventDecoder = new EventDecoder();        // decodes received data and creates Events

                eventDecoder.startEvent(id, nodeId, link, frame,
                                        fragment, "", "",                    // Fragment, query, post
                                        referrerNodeId,
                                        parentFrame,
                                        parentNodeId,
										windowSize,
										clickPos,
                                        history );

                FileGenerator rg = new FileGenerator("resources/scone/proxy/pixel.gif", "image/gif");
                g = rg;
                
                // Debuggin data
                // System.out.println("LINK fragment = "+fragment);
                // System.out.println("linkId   = " + linkId);
                // System.out.println("linkTime = " + linkTime);
                // System.out.println("LinkType = " + Long.toBinaryString(linkType));

                // User clicked a link. ---------------------------------------------------------------------------------
            	}
                else if (file.startsWith("/_event")) 
                {
                    event = "event";
                    getAccessKey("/_event");

                    parseBrowserData();

                    // get event name
                    String eventName = formParameter.getProperty("event");
                    if (eventName == null) {
                    	eventName = "";
                    }

                    // get load time
                    String timeString = formParameter.getProperty("time");
                    if (timeString == null) {
                        timeString = "0";
                    }
                    long time = Long.parseLong(timeString);            // Convert to long

                    // get current Address...
                    String address = formParameter.getProperty("address");
                    if (address == null) {
                        address = "";
                    }

                    // Which nodeId?
                    String nodeId = formParameter.getProperty("nodeID");
                    if (nodeId == null) {
                        nodeId = "";
                    }                               // was it available?
                    
                    if (nodeId.equals("undefined") || nodeId.equals("")) {
                        NetNode newNode = NetNodeCache.get(address);
                        nodeId = newNode.getNodeId();
                    }
                    
                    eventDecoder = new EventDecoderFirefox();        // decodes received data and creates Events for Firefox
                    eventDecoder.event(id, nodeId, time, frame,
                    						eventName,
											address,
                                            history );
                    
                    FileGenerator rg = new FileGenerator("resources/scone/proxy/pixel.gif", "image/gif");
                    g = rg;
                    
                    // Debugging data
                    //System.out.println("Event    = " + eventName);
                    //System.out.println("Address  = " + address);
                    //System.out.println("nodeId   = " + nodeId);
                    //System.out.println("userId   = " + userId);
                    //System.out.println("time     = " + time    );
                    //System.out.println("frame    = " + frame   );
                    //System.out.println("history  = " + history );
                    // System.out.println("LinkType = " + Long.toBinaryString(linkType));

            } else {
                // Create response from file ------------------------------------------
                // System.out.println("Returning: "+file);
                String ext = file.substring(file.lastIndexOf(".") + 1);
                FileGenerator rg = new FileGenerator("resources/scone/proxy/" + file, getContentType(ext));
                g = rg;
            }
        }

        // Create response from file
        // System.out.println(file);
        // String       ext          = file.substring(file.lastIndexOf(".")+1);
        // com.ibm.wbi.protocol.http.beans.ResourceGenerator g = new com.ibm.wbi.protocol.http.beans.ResourceGenerator("resources/scone/proxy/"+file,getContentType(ext),true);

        // Create response on the fly...
        // StaticHtmlGenerator g = new StaticHtmlGenerator(); //Return generated document to the client
        // g.setStaticHtml("window.href='http://tracking.scone.de/register.html'");

        response = g.getHttpResponse();                   // Get http response header
        response.add("Pragma", "no-cache");               // HTTP 1.0 (Most browsers)
        response.add("Cache-Control", "no-store, no-cache, must-revalidate, private");  // HTTP 1.1: IE 5&6
        response.add("Cache-Control", "post-check=0, pre-check=0");
        response.add("Cache-Control", "max-age=0");
        response.add("Expires", "Tue, 13 Dec 1988 09:00:00 GMT");   // Page is expired...
        SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.US); // 09-Nov-2030 23:59:00 GMT;
        String dateString = formatter.format(new Date())+" GMT"; // Dirty workaround...
        // System.out.println(dateString);
        response.add("Last-Modified", dateString);   // Page is expired...

        // response.setResponseCode(408);    // Probleme beim IE!
        // response.setCache(false);

        // Send Response to Browser
        try {
            forwardRequest(g, e);
        } catch (java.io.IOException ex) {
            System.out.println("IOError sending response in AccessTracking2Meg!");
        }

    }

    /*
     * Create most important mime types from file extensions
     */
    private String getContentType(String ext) {
        ext = ext.toLowerCase();
        if (ext.equals("txt")) {
            return "text/txt";
        }
        if (ext.equals("css")) {
            return "text/css";
        }
        if (ext.equals("js")) {
            return "application/x-javascript";
        }
        if (ext.equals("gif")) {
            return "image/gif";
        }
        if (ext.equals("jpg")) {
            return "image/jpeg";
        }
        return "text/html";
    }

    /*
     * Create nodeId, start and frame from query string
     */
    private void getAccessKey(String filenameStart) {
        // get nodeId from filename. This is not a query parameter, as there are otherwise problems
        // with frames.

        // System.out.println("\nevent = " + event);
        
        try {
            nodeId = file.substring(filenameStart.length());
            nodeURI  = "";
            query    = "";
            fragment = "";
            // was it available?
            if (nodeId == null || nodeId.length() == 0) { 
                nodeId   = "";
            } else {
                NetNode node = NetNodeCache.getById(nodeId);
                if (node!=null) {
                    nodeURI = node.toString();
                    query   = node.getQuery();
                    fragment= node.getFragment();
                } 
            }

            // get start time
            String startString = formParameter.getProperty("start");

            if (startString == null) {
                startString = "0";
            }
            start = Long.parseLong(startString);            // Convert to long
            // Date startDate = new Date(start); System.out.println(startDate);

            // Name of this frame/window
            frame = formParameter.getProperty("frame");
            if (frame == null) {
                frame = "";
            }
            //System.out.println("nodeId = " + nodeId);
            //System.out.println("start = " + startString);
            //System.out.println("frame = " + frame);
            //System.out.println("fragment = " + fragment);
        } catch (NumberFormatException ex) {
            System.err.println("AccessTrackingMeg: Error creating numbers: " + file);
            System.err.println("nodeId = " + nodeId);
            System.err.println("start = " + start);
            System.err.println("frame = " + frame);
            nodeId = "0";
            start = 0;
            frame = "";
        }
    }

    /*
     * What is the parent, the frame name, the parent frame name, the referrer etc.
     * This method is called from _start and from _loaded to miminize problems
     * caussed by "§%§%" browser JS-bugs...
     */
    private void parseBrowserData() {
        
        // Browser name
        browser = formParameter.getProperty("browser");
        if (browser == null) {
            browser = "";
        }

        // Parent frame name
        parentFrame = formParameter.getProperty("parent");
        if (parentFrame == null) {
            parentFrame = "";
        }

        // int referrer (NodeId: where did the user come from...)
        String referrerUri = formParameter.getProperty("referrer");
        if (referrerUri == null) {
            referrerUri = "";
        } else {
            try {
                NetNode referrerNetNode = NetNodeCache.get(referrerUri);

                referrerNodeId = referrerNetNode.getNodeId();
            } catch (Exception uriException) {
                System.out.println("Exception: referrerUri = " + referrerUri);
                if (referrerUri.equals("[Unknown Origin]")) {
                    // action |= BOOKMARK;
                }  // Bookmark for Netscape ???
                if (referrerUri.equals("[New Window]")) {
                    // action |= NEWWINDOW;
                }      // New window was opened and name was assigned
            }
        }

        // Parent Frame Uri, if available: int parentNodeId
        String parentUri = formParameter.getProperty("parentUri");
        if (parentUri == null) {
            parentUri = "";
            parentNodeId = "";
        } else {
            NetNode parentNetNode = NetNodeCache.get(parentUri);
            parentNodeId = parentNetNode.getNodeId();
        }

        // Length of History...
        String historyString = formParameter.getProperty("history");
        if (historyString == null || historyString.equals("")) {
            historyString = "0";
        }
        history = Integer.parseInt(historyString);            // Convert to int

        //System.out.println("parent = " + parentFrame);
        // System.out.println("referrerUri = " + referrerUri);
        //System.out.println("referrer Id = " + referrerNodeId);
        //System.out.println("parentUri = " + parentUri);
        //System.out.println("parent Id = " + parentNodeId);
        //System.out.println("history = " + history);
        //System.out.println("browser = " + browser);
    }

}
