<commit_before>/* global APP */
var EventEmitter = require("events");
var RTCBrowserType = require("./RTCBrowserType");
var RTCUtils = require("./RTCUtils.js");
var LocalStream = require("./LocalStream.js");
var DataChannels = require("./DataChannels");
var MediaStream = require("./MediaStream.js");
var DesktopSharingEventTypes
    = require("../../service/desktopsharing/DesktopSharingEventTypes");
var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
var RTCEvents = require("../../service/RTC/RTCEvents.js");
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
var UIEvents = require("../../service/UI/UIEvents");

var eventEmitter = new EventEmitter();

function getMediaStreamUsage()
{
    var result = {
        audio: true,
        video: true
    };

    /** There are some issues with the desktop sharing
     * when this property is enabled.
     * WARNING: We must change the implementation to start video/audio if we
     * receive from the focus that the peer is not muted.

     var isSecureConnection = window.location.protocol == "https:";

    if(config.disableEarlyMediaPermissionRequests || !isSecureConnection)
    {
        result = {
            audio: false,
            video: false
        };

    }
    **/

    return result;
}

var RTC = {
    // Exposes DataChannels to public consumption (e.g. jitsi-meet-torture)
    // without the necessity to require the module.
    "DataChannels": DataChannels,

    rtcUtils: null,
    devices: {
        audio: true,
        video: true
    },
    remoteStreams: {},
    localAudio: null,
    localVideo: null,
    addStreamListener: function (listener, eventType) {
        eventEmitter.on(eventType, listener);
    },
    addListener: function (type, listener) {
        eventEmitter.on(type, listener);
    },
    removeStreamListener: function (listener, eventType) {
        if(!(eventType instanceof StreamEventTypes))
            throw "Illegal argument";

        eventEmitter.removeListener(eventType, listener);
    },
    createLocalStream: function (stream, type, change, videoType,
                                 isMuted, isGUMStream) {

        var localStream =
            new LocalStream(stream, type, eventEmitter, videoType, isGUMStream);
        if(isMuted === true)
            localStream.setMute(true);

        if (MediaStreamType.AUDIO_TYPE === type) {
            this.localAudio = localStream;
        } else {
            this.localVideo = localStream;
        }
        var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED;
        if(change)
            eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED;

        eventEmitter.emit(eventType, localStream, isMuted);
        return localStream;
    },
    createRemoteStream: function (data, ssrc) {
        var jid = data.peerjid || APP.xmpp.myJid();

        // check the video muted state from last stored presence if any
        var muted = false;
        var pres = APP.xmpp.getLastPresence(jid);
        if (pres && pres.videoMuted) {
            muted = pres.videoMuted;
        }

        var self = this;
        [MediaStreamType.AUDIO_TYPE, MediaStreamType.VIDEO_TYPE].forEach(
            function (type) {
            var tracks =
                type == MediaStreamType.AUDIO_TYPE
                ? data.stream.getAudioTracks() : data.stream.getVideoTracks();
            if (!tracks || !Array.isArray(tracks) || !tracks.length) {
                console.log("Not creating a(n) " + type + " stream: no tracks");
                return;
            }

            var remoteStream = new MediaStream(data, ssrc,
                RTCBrowserType.getBrowserType(), eventEmitter, muted, type);

            if (!self.remoteStreams[jid]) {
                self.remoteStreams[jid] = {};
            }
            self.remoteStreams[jid][type] = remoteStream;
            eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED,
                remoteStream);
        });
    },
    getPCConstraints: function () {
        return this.rtcUtils.pc_constraints;
    },
    getUserMediaWithConstraints:function(um, success_callback,
                                         failure_callback, resolution,
                                         bandwidth, fps, desktopStream)
    {
        return this.rtcUtils.getUserMediaWithConstraints(um, success_callback,
            failure_callback, resolution, bandwidth, fps, desktopStream);
    },
    attachMediaStream:  function (elSelector, stream) {
        this.rtcUtils.attachMediaStream(elSelector, stream);
    },
    getStreamID:  function (stream) {
        return this.rtcUtils.getStreamID(stream);
    },
    getVideoSrc: function (element) {
        return this.rtcUtils.getVideoSrc(element);
    },
    setVideoSrc: function (element, src) {
        this.rtcUtils.setVideoSrc(element, src);
    },
    getVideoElementName: function () {
        return RTCBrowserType.isTemasysPluginUsed() ? 'object' : 'video';
    },
    dispose: function() {
        if (this.rtcUtils) {
            this.rtcUtils = null;
        }
    },
    stop:  function () {
        this.dispose();
    },
    start: function () {
        var self = this;
        APP.desktopsharing.addListener(
            DesktopSharingEventTypes.NEW_STREAM_CREATED,
            function (stream, isUsingScreenStream, callback) {
                self.changeLocalVideo(stream, isUsingScreenStream, callback);
        });
        APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function(event) {
            DataChannels.init(event.peerconnection, eventEmitter);
        });
        APP.UI.addListener(UIEvents.SELECTED_ENDPOINT,
            DataChannels.handleSelectedEndpointEvent);
        APP.UI.addListener(UIEvents.PINNED_ENDPOINT,
            DataChannels.handlePinnedEndpointEvent);

        // In case of IE we continue from 'onReady' callback
        // passed to RTCUtils constructor. It will be invoked by Temasys plugin
        // once it is initialized.
        var onReady = function () {
            eventEmitter.emit(RTCEvents.RTC_READY, true);
            self.rtcUtils.obtainAudioAndVideoPermissions(
                null, null, getMediaStreamUsage());
        };

        this.rtcUtils = new RTCUtils(this, eventEmitter, onReady);

        // Call onReady() if Temasys plugin is not used
        if (!RTCBrowserType.isTemasysPluginUsed()) {
            onReady();
        }
    },
    muteRemoteVideoStream: function (jid, value) {
        var stream;

        if(this.remoteStreams[jid] &&
            this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
            stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
        }

        if(!stream)
            return true;

        if (value != stream.muted) {
            stream.setMute(value);
            return true;
        }
        return false;
    },
    changeLocalVideo: function (stream, isUsingScreenStream, callback) {
        var oldStream = this.localVideo.getOriginalStream();
        var type = (isUsingScreenStream ? "screen" : "camera");
        var localCallback = callback;
        if(this.localVideo.isMuted() && this.localVideo.videoType !== type) {
            localCallback = function() {
                APP.xmpp.setVideoMute(false, function(mute) {
                    eventEmitter.emit(RTCEvents.VIDEO_MUTE, mute);
                });

                callback();
            };
        }
        // FIXME: Workaround for FF/IE/Safari
        if (stream && stream.videoStream) {
            stream = stream.videoStream;
        }
        var videoStream = this.rtcUtils.createStream(stream, true);
        this.localVideo =
            this.createLocalStream(videoStream, "video", true, type);
        // Stop the stream
        this.stopMediaStream(oldStream);

        APP.xmpp.switchStreams(videoStream, oldStream,localCallback);
    },
    changeLocalAudio: function (stream, callback) {
        var oldStream = this.localAudio.getOriginalStream();
        var newStream = this.rtcUtils.createStream(stream);
        this.localAudio
            = this.createLocalStream(
                    newStream, MediaStreamType.AUDIO_TYPE, true);
        // Stop the stream
        this.stopMediaStream(oldStream);
        APP.xmpp.switchStreams(newStream, oldStream, callback, true);
    },
    isVideoMuted: function (jid) {
        if (jid === APP.xmpp.myJid()) {
            var localVideo = APP.RTC.localVideo;
            return (!localVideo || localVideo.isMuted());
        } else {
            if (!APP.RTC.remoteStreams[jid] ||
                !APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
                return null;
            }
            return APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted;
        }
    },
    setVideoMute: function (mute, callback, options) {
        if (!this.localVideo)
            return;

        if (mute == APP.RTC.localVideo.isMuted())
        {
            APP.xmpp.sendVideoInfoPresence(mute);
            if (callback)
                callback(mute);
        }
        else
        {
            APP.RTC.localVideo.setMute(mute);
            APP.xmpp.setVideoMute(
                mute,
                callback,
                options);
        }
    },
    setDeviceAvailability: function (devices) {
        if(!devices)
            return;
        if(devices.audio === true || devices.audio === false)
            this.devices.audio = devices.audio;
        if(devices.video === true || devices.video === false)
            this.devices.video = devices.video;
        eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, this.devices);
    },
    /**
     * A method to handle stopping of the stream.
     * One point to handle the differences in various implementations.
     * @param mediaStream MediaStream object to stop.
     */
    stopMediaStream: function (mediaStream) {
        mediaStream.getTracks().forEach(function (track) {
            // stop() not supported with IE
            if (track.stop) {
                track.stop();
            }
        });

        // leave stop for implementation still using it
        if (mediaStream.stop) {
            mediaStream.stop();
        }
    },
    /**
     * Adds onended/inactive handler to a MediaStream.
     * @param mediaStream a MediaStream to attach onended/inactive handler
     * @param handler the handler
     */
    addMediaStreamInactiveHandler: function (mediaStream, handler) {
        if (mediaStream.addEventListener) {
            // chrome
            if(typeof mediaStream.active !== "undefined")
                mediaStream.inactive = handler;
            else
                mediaStream.onended = handler;
        } else {
            // themasys
            mediaStream.attachEvent('ended', function () {
                handler(mediaStream);
            });
        }
    },
    /**
     * Removes onended/inactive handler.
     * @param mediaStream the MediaStream to remove the handler from.
     * @param handler the handler to remove.
     */
    removeMediaStreamInactiveHandler: function (mediaStream, handler) {
        if (mediaStream.removeEventListener) {
            // chrome
            if(typeof mediaStream.active !== "undefined")
                mediaStream.inactive = null;
            else
                mediaStream.onended = null;
        } else {
            // themasys
            mediaStream.detachEvent('ended', handler);
        }
    }
};

module.exports = RTC;
<commit_msg>Fixes wrong handler name, which causes adding multiple local video tags in the local video.<commit_after>/* global APP */
var EventEmitter = require("events");
var RTCBrowserType = require("./RTCBrowserType");
var RTCUtils = require("./RTCUtils.js");
var LocalStream = require("./LocalStream.js");
var DataChannels = require("./DataChannels");
var MediaStream = require("./MediaStream.js");
var DesktopSharingEventTypes
    = require("../../service/desktopsharing/DesktopSharingEventTypes");
var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
var RTCEvents = require("../../service/RTC/RTCEvents.js");
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
var UIEvents = require("../../service/UI/UIEvents");

var eventEmitter = new EventEmitter();

function getMediaStreamUsage()
{
    var result = {
        audio: true,
        video: true
    };

    /** There are some issues with the desktop sharing
     * when this property is enabled.
     * WARNING: We must change the implementation to start video/audio if we
     * receive from the focus that the peer is not muted.

     var isSecureConnection = window.location.protocol == "https:";

    if(config.disableEarlyMediaPermissionRequests || !isSecureConnection)
    {
        result = {
            audio: false,
            video: false
        };

    }
    **/

    return result;
}

var RTC = {
    // Exposes DataChannels to public consumption (e.g. jitsi-meet-torture)
    // without the necessity to require the module.
    "DataChannels": DataChannels,

    rtcUtils: null,
    devices: {
        audio: true,
        video: true
    },
    remoteStreams: {},
    localAudio: null,
    localVideo: null,
    addStreamListener: function (listener, eventType) {
        eventEmitter.on(eventType, listener);
    },
    addListener: function (type, listener) {
        eventEmitter.on(type, listener);
    },
    removeStreamListener: function (listener, eventType) {
        if(!(eventType instanceof StreamEventTypes))
            throw "Illegal argument";

        eventEmitter.removeListener(eventType, listener);
    },
    createLocalStream: function (stream, type, change, videoType,
                                 isMuted, isGUMStream) {

        var localStream =
            new LocalStream(stream, type, eventEmitter, videoType, isGUMStream);
        if(isMuted === true)
            localStream.setMute(true);

        if (MediaStreamType.AUDIO_TYPE === type) {
            this.localAudio = localStream;
        } else {
            this.localVideo = localStream;
        }
        var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED;
        if(change)
            eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED;

        eventEmitter.emit(eventType, localStream, isMuted);
        return localStream;
    },
    createRemoteStream: function (data, ssrc) {
        var jid = data.peerjid || APP.xmpp.myJid();

        // check the video muted state from last stored presence if any
        var muted = false;
        var pres = APP.xmpp.getLastPresence(jid);
        if (pres && pres.videoMuted) {
            muted = pres.videoMuted;
        }

        var self = this;
        [MediaStreamType.AUDIO_TYPE, MediaStreamType.VIDEO_TYPE].forEach(
            function (type) {
            var tracks =
                type == MediaStreamType.AUDIO_TYPE
                ? data.stream.getAudioTracks() : data.stream.getVideoTracks();
            if (!tracks || !Array.isArray(tracks) || !tracks.length) {
                console.log("Not creating a(n) " + type + " stream: no tracks");
                return;
            }

            var remoteStream = new MediaStream(data, ssrc,
                RTCBrowserType.getBrowserType(), eventEmitter, muted, type);

            if (!self.remoteStreams[jid]) {
                self.remoteStreams[jid] = {};
            }
            self.remoteStreams[jid][type] = remoteStream;
            eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED,
                remoteStream);
        });
    },
    getPCConstraints: function () {
        return this.rtcUtils.pc_constraints;
    },
    getUserMediaWithConstraints:function(um, success_callback,
                                         failure_callback, resolution,
                                         bandwidth, fps, desktopStream)
    {
        return this.rtcUtils.getUserMediaWithConstraints(um, success_callback,
            failure_callback, resolution, bandwidth, fps, desktopStream);
    },
    attachMediaStream:  function (elSelector, stream) {
        this.rtcUtils.attachMediaStream(elSelector, stream);
    },
    getStreamID:  function (stream) {
        return this.rtcUtils.getStreamID(stream);
    },
    getVideoSrc: function (element) {
        return this.rtcUtils.getVideoSrc(element);
    },
    setVideoSrc: function (element, src) {
        this.rtcUtils.setVideoSrc(element, src);
    },
    getVideoElementName: function () {
        return RTCBrowserType.isTemasysPluginUsed() ? 'object' : 'video';
    },
    dispose: function() {
        if (this.rtcUtils) {
            this.rtcUtils = null;
        }
    },
    stop:  function () {
        this.dispose();
    },
    start: function () {
        var self = this;
        APP.desktopsharing.addListener(
            DesktopSharingEventTypes.NEW_STREAM_CREATED,
            function (stream, isUsingScreenStream, callback) {
                self.changeLocalVideo(stream, isUsingScreenStream, callback);
        });
        APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function(event) {
            DataChannels.init(event.peerconnection, eventEmitter);
        });
        APP.UI.addListener(UIEvents.SELECTED_ENDPOINT,
            DataChannels.handleSelectedEndpointEvent);
        APP.UI.addListener(UIEvents.PINNED_ENDPOINT,
            DataChannels.handlePinnedEndpointEvent);

        // In case of IE we continue from 'onReady' callback
        // passed to RTCUtils constructor. It will be invoked by Temasys plugin
        // once it is initialized.
        var onReady = function () {
            eventEmitter.emit(RTCEvents.RTC_READY, true);
            self.rtcUtils.obtainAudioAndVideoPermissions(
                null, null, getMediaStreamUsage());
        };

        this.rtcUtils = new RTCUtils(this, eventEmitter, onReady);

        // Call onReady() if Temasys plugin is not used
        if (!RTCBrowserType.isTemasysPluginUsed()) {
            onReady();
        }
    },
    muteRemoteVideoStream: function (jid, value) {
        var stream;

        if(this.remoteStreams[jid] &&
            this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
            stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
        }

        if(!stream)
            return true;

        if (value != stream.muted) {
            stream.setMute(value);
            return true;
        }
        return false;
    },
    changeLocalVideo: function (stream, isUsingScreenStream, callback) {
        var oldStream = this.localVideo.getOriginalStream();
        var type = (isUsingScreenStream ? "screen" : "camera");
        var localCallback = callback;
        if(this.localVideo.isMuted() && this.localVideo.videoType !== type) {
            localCallback = function() {
                APP.xmpp.setVideoMute(false, function(mute) {
                    eventEmitter.emit(RTCEvents.VIDEO_MUTE, mute);
                });

                callback();
            };
        }
        // FIXME: Workaround for FF/IE/Safari
        if (stream && stream.videoStream) {
            stream = stream.videoStream;
        }
        var videoStream = this.rtcUtils.createStream(stream, true);
        this.localVideo =
            this.createLocalStream(videoStream, "video", true, type);
        // Stop the stream
        this.stopMediaStream(oldStream);

        APP.xmpp.switchStreams(videoStream, oldStream,localCallback);
    },
    changeLocalAudio: function (stream, callback) {
        var oldStream = this.localAudio.getOriginalStream();
        var newStream = this.rtcUtils.createStream(stream);
        this.localAudio
            = this.createLocalStream(
                    newStream, MediaStreamType.AUDIO_TYPE, true);
        // Stop the stream
        this.stopMediaStream(oldStream);
        APP.xmpp.switchStreams(newStream, oldStream, callback, true);
    },
    isVideoMuted: function (jid) {
        if (jid === APP.xmpp.myJid()) {
            var localVideo = APP.RTC.localVideo;
            return (!localVideo || localVideo.isMuted());
        } else {
            if (!APP.RTC.remoteStreams[jid] ||
                !APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
                return null;
            }
            return APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted;
        }
    },
    setVideoMute: function (mute, callback, options) {
        if (!this.localVideo)
            return;

        if (mute == APP.RTC.localVideo.isMuted())
        {
            APP.xmpp.sendVideoInfoPresence(mute);
            if (callback)
                callback(mute);
        }
        else
        {
            APP.RTC.localVideo.setMute(mute);
            APP.xmpp.setVideoMute(
                mute,
                callback,
                options);
        }
    },
    setDeviceAvailability: function (devices) {
        if(!devices)
            return;
        if(devices.audio === true || devices.audio === false)
            this.devices.audio = devices.audio;
        if(devices.video === true || devices.video === false)
            this.devices.video = devices.video;
        eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, this.devices);
    },
    /**
     * A method to handle stopping of the stream.
     * One point to handle the differences in various implementations.
     * @param mediaStream MediaStream object to stop.
     */
    stopMediaStream: function (mediaStream) {
        mediaStream.getTracks().forEach(function (track) {
            // stop() not supported with IE
            if (track.stop) {
                track.stop();
            }
        });

        // leave stop for implementation still using it
        if (mediaStream.stop) {
            mediaStream.stop();
        }
    },
    /**
     * Adds onended/inactive handler to a MediaStream.
     * @param mediaStream a MediaStream to attach onended/inactive handler
     * @param handler the handler
     */
    addMediaStreamInactiveHandler: function (mediaStream, handler) {
        if (mediaStream.addEventListener) {
            // chrome
            if(typeof mediaStream.active !== "undefined")
                mediaStream.oninactive = handler;
            else
                mediaStream.onended = handler;
        } else {
            // themasys
            mediaStream.attachEvent('ended', function () {
                handler(mediaStream);
            });
        }
    },
    /**
     * Removes onended/inactive handler.
     * @param mediaStream the MediaStream to remove the handler from.
     * @param handler the handler to remove.
     */
    removeMediaStreamInactiveHandler: function (mediaStream, handler) {
        if (mediaStream.removeEventListener) {
            // chrome
            if(typeof mediaStream.active !== "undefined")
                mediaStream.oninactive = null;
            else
                mediaStream.onended = null;
        } else {
            // themasys
            mediaStream.detachEvent('ended', handler);
        }
    }
};

module.exports = RTC;
<|endoftext|>


<commit_before>/**
 * Simple HTTP Server
 *
 * Author: phen
 *
 * @param {Object} opts
 * @param {Object} appLifeCycle - handle different life cycle phases for registering requests to the express app instance
 * @param {boolean} auth - disable the auth handling to implement by your own
 * @param {string} secret - the cookie secret name for cookie access
 * @param {number} port - the cookie secret name for cookie access
 * @param {string} fileStorageName - path to store the files
 * @param {string} fourOFourFile - path of the 404.html which will be shown if the file is not available (default is the dragKing own file)
 * @param {function} appLifeCycle.phase1 - executed before the files listener is attached
 * @param {function} appLifeCycle.fileFilter - filter for files and folders which will not be send to client (return file name or undefined to filter out)
 * @param {function} appLifeCycle.onUploadFile - listener will be called if file is successfully saves on file system
 * @param {function} appLifeCycle.onDeleteFile - listener will be called if file is successfully deleted from file system
 * @returns {function}
 */
function main(opts, appLifeCycle) {

    var fs = require('fs'),
        wsConnection = require('./server/lib/wsConnection'),
        cookieParser = require('cookie-parser'),
        sessionStore = require('./server/lib/sessionStore'),
        packageJSON = require('./package.json'),
        bodyParser = require('body-parser'),
        folderUtil = require('./lib/folderUtil'),
        changeHistoryLogger = require('./server/lib/changeHistoryLogger'),
        express = require('express'),
        busboy = require('connect-busboy'),
        serveIndex = require('serve-index'),
        thumbNail = require('./lib/thumbNail')(opts.fileStorageName, 'tmb_'),
        app,
        finalhandler = require('finalhandler'),
        serveStatic = require('serve-static'),
        serve = serveStatic(opts.dirName),
        index = serveIndex(opts.dirName, {'icons': true}),
        acceptedImageExtensions = ['jpeg', 'jpg', 'png', 'gif'];

    app = express();
    app.use(busboy());

    app.get(['/dist/*'], function (req, res) {
        var done = finalhandler(req, res);
        serve(req, res, function onNext(err) {
            if (err) {
                return done(err);
            }
            index(req, res, done);
        });
    });

    app.get('/files*', function (req, res) {
        var done = finalhandler(req, res);
        serve(req, res, function onNext(err) {
            if (err) {
                return done(err);
            }
            index(req, res, done);
        });
    });

    // use bodyParser middleware for handling request bodies (express does *not* provide that feature out-of-the-box).
    // since we only have one case of that (POST to /login where username, password are in the body) and that one is url-encoded,
    // we only need that flavor of bodyParser. about the "extended" property, see https://github.com/expressjs/body-parser#bodyparserurlencodedoptions
    app.use(bodyParser.urlencoded({ extended: false }));
    // same for parsing cookie
    app.use(cookieParser());

    appLifeCycle && appLifeCycle.phase1 && appLifeCycle.phase1(app);
    app.get(/^((?!^(\/dist|\/bower_components)).)*$/, function(req, res, next) {

        if (packageJSON.config.auth) {
            // file request
            let isAuth = req.session && req.session.authId;
            if (!/\./.test(req.path) && !isAuth) {
                // TODO sending the login page only makes sense for browser requests. if anybody is e.g. using curl to
                // retrieve message bundles, we should only return a 401 but no content
                res.sendFile(__dirname + '/auth.html');
            } else {
                next();
            }
        } else {
            next();
        }

    });

    app.post('/uploadFile', function (req, res, next) {
        if (packageJSON.config.auth) {
            if (req.session && (req.session.isMaintainer) || req.session.isAdmin) {
                if (req.session.isAdmin) {
                    next();
                } else if (!/.json/.test(req.query.filename)) {
                    next();
                } else {
                    res.status(401).send('Not authorized');
                }
            } else {
                res.status(401).send('Not authorized');
            }
        } else {
            // res.status(401).send('Not authorized');
            next()
        }
    });

    /**
     * Limited restrictions!
     *
     * visitors:
     *  * are not allowed at all
     * maintainer:
     *  * not allowed to delete .json files
     * admins:
     *  * allowed to do everything
     */
    app.post('/deleteFile', function (req, res, next) {
        if (packageJSON.config.auth) {
            if (req.session && req.session.isMaintainer || req.session.isAdmin) {
                if (req.session.isAdmin) {
                    next();
                } else if (!/.json/.test(req.query.filename)) {
                    next();
                } else {
                    res.status(401).send('Not authorized');
                }
            } else {
                res.status(401).send('Not authorized');
            }
        } else {
            // res.status(401).send('Not authorized');
            next()
        }
    });
    /**
     * match except for folder dist
     *
     * If the URL has a dot inside it expect to send a files. Otherwise it sends the index.
     */
    app.get(/^((?!^(\/dist)).)*$/, function (req, res) {
        if (/\./.test(req.path)) {
            // contains a . - looks like a file request so check the files system
            fs.exists(decodeURI(opts.fileStorageName + req.path), function (exists) {
                if (exists) {
                    // not sure if it is good by default but - needs to be configurable
                    res.header("Access-Control-Allow-Origin", "*");
                    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

                    if (/\?tmb/.test(req.url)) {

                        thumbNail.create(decodeURI(req.path), function (file) {
                            if (file) {
                                res.sendFile(file);
                            } else {
                                res.sendFile(decodeURI(opts.fileStorageName + req.path));
                            }
                        });

                    } else {
                        res.sendFile(decodeURI(opts.fileStorageName + req.path), {dotfiles : 'allow'});
                    }
                } else {
                    // no file found - send 404 file
                    console.log('main:fileName', __dirname);
                    res.status(404).sendFile(opts.fourOFourFile ? opts.fourOFourFile : __dirname + '/404.html');
                }
            });

        } else {
            // send index
            res.sendFile(opts.dirName + 'index.html');

        }
    });

    app.post('/uploadFile', function (req, res) {
        var fstream, folder = folderUtil.formatFolder(req.query.folder);

        req.pipe(req.busboy);
        req.busboy.on('file', function (fieldname, file, filename) {
            // replace all spaces with underscores
            // TODO it's not a good idea to rename file - because there are people they put spaces in a file name
            var fName = filename; //.split(' ').join('_');

            function writeFile() {

                fstream = fs.createWriteStream(opts.fileStorageName + folder + fName);
                file.pipe(fstream);
                fstream.on('close', function () {
                    // TODO add correct type
                    var extension = fName.split('.').pop();
                    if (extension && acceptedImageExtensions.indexOf(extension.toLowerCase()) !== -1) {
                        res.status(200).send({file: folder + fName, name: fName, type: 'image/jpg'});
                    } else {
                        res.status(200).send({file: folder + fName, name: fName, type: extension});
                    }
                });
            }
            changeHistoryLogger.write(opts.fileStorageName, folder + fName, 'upload', req.session.authId || 'anonymous');
            appLifeCycle && appLifeCycle.onUploadFile && appLifeCycle.onUploadFile(req, {
                rootFolder : opts.fileStorageName,
                fileName : folder + fName
            });
            folderUtil.createFolder(opts.fileStorageName, folder, writeFile);
        });
    });

    /**
     * get all available files
     */
    app.post('/getFiles', function (req, res) {
        var folder = '';

        req.on("data", function (chunk) {
            folder += chunk.toString();
        });

        req.on("end", function () {
            folder = folderUtil.formatFolder(folder);
            fs.readdir(opts.fileStorageName + folder, function (err, files) {

                var fileList = [],
                    length;

                if (err === null) {
                    files = files.filter(function (fileName) {
                        return fileName.split('/').pop().startsWith('tmb_') ? undefined : fileName
                    });
                    if (appLifeCycle && appLifeCycle.fileFilter) {
                        files = files.filter(appLifeCycle.fileFilter);
                    }
                    length = files.length;
                    files.forEach(function (file) {
                        fs.stat(opts.fileStorageName + folder + file, function (err, stats) {
                            if (stats.isFile()) {
                                // TODO add correct type
                                var extension = file.split('.').pop();

                                if (extension && acceptedImageExtensions.indexOf(extension.toLowerCase()) !== -1) {
                                    fileList.push({file: folder + file, name: file, type: 'image/jpg'});
                                } else {
                                    fileList.push({file: folder + file, name: file, type: extension});
                                }
                            } else if (stats.isDirectory()) {
                                // filter out directories - if we need directories we should ask separately for it
                                console.log('Found a directory named:', file);
                            }
                            length--;
                            if (length <= 0) {
                                res.status(200).send(fileList);
                            }
                        });
                    });
                }
            });
        });
    });

    /**
     * get all available folders
     */
    app.post('/getFolders', function (req, res) {
        // get a list of all folders
        var folder = '';

        req.on("data", function (chunk) {
            folder += chunk.toString();
        });

        req.on("end", function () {
            folder = folderUtil.formatFolder(folder);
            fs.readdir(opts.fileStorageName + folder, function (err, files) {
                var fileList = [],
                    length;

                if (err === null) {
                    length = files.length;
                    files.forEach(function (file) {
                        fs.stat(opts.fileStorageName + folder + file, function (err, stats) {
                            if (err) {
                                console.log("app:path not exists:", err);
                                return;
                            }
                            if (stats.isDirectory()) {
                                fileList.push(file);
                            }
                            length--;
                            if (length <= 0) {
                                res.status(200).send(fileList);
                            }
                        });
                    });
                }
            });
        });
    });

    /**
     * delete a file
     */
    app.post('/deleteFile', function (req, res) {
        var fileName;
        if (req.query.hasOwnProperty('filename')) {
            fileName = req.query.filename;
            if (fileName[0] !== '/') {
                fileName = '/' + fileName;
            }
            fs.unlink(opts.fileStorageName + fileName, function () {
                changeHistoryLogger.write(opts.fileStorageName, fileName, 'delete', req.session.authId || 'anonymous');
                appLifeCycle && appLifeCycle.onDeleteFile && appLifeCycle.onDeleteFile(req, {
                    rootFolder : opts.fileStorageName,
                    fileName : fileName
                });
                res.status(200).send(req.query.filename);
            });
            thumbNail.remove(fileName);
        } else {
            res.status(200).send(false);
        }
    });

    let server;

    server = app.listen(opts.port, function () {
        console.log('server started on port %d', opts.port);
    });

    // initialize the json persist via websocket
    wsConnection(server, {
        secret : opts.secret,
        dirName : opts.fileStorageName
    });

    return app;
}

module.exports = main;<commit_msg>clean up console log<commit_after>/**
 * Simple HTTP Server
 *
 * Author: phen
 *
 * @param {Object} opts
 * @param {Object} appLifeCycle - handle different life cycle phases for registering requests to the express app instance
 * @param {boolean} auth - disable the auth handling to implement by your own
 * @param {string} secret - the cookie secret name for cookie access
 * @param {number} port - the cookie secret name for cookie access
 * @param {string} fileStorageName - path to store the files
 * @param {string} fourOFourFile - path of the 404.html which will be shown if the file is not available (default is the dragKing own file)
 * @param {function} appLifeCycle.phase1 - executed before the files listener is attached
 * @param {function} appLifeCycle.fileFilter - filter for files and folders which will not be send to client (return file name or undefined to filter out)
 * @param {function} appLifeCycle.onUploadFile - listener will be called if file is successfully saves on file system
 * @param {function} appLifeCycle.onDeleteFile - listener will be called if file is successfully deleted from file system
 * @returns {function}
 */
function main(opts, appLifeCycle) {

    var fs = require('fs'),
        wsConnection = require('./server/lib/wsConnection'),
        cookieParser = require('cookie-parser'),
        sessionStore = require('./server/lib/sessionStore'),
        packageJSON = require('./package.json'),
        bodyParser = require('body-parser'),
        folderUtil = require('./lib/folderUtil'),
        changeHistoryLogger = require('./server/lib/changeHistoryLogger'),
        express = require('express'),
        busboy = require('connect-busboy'),
        serveIndex = require('serve-index'),
        thumbNail = require('./lib/thumbNail')(opts.fileStorageName, 'tmb_'),
        app,
        finalhandler = require('finalhandler'),
        serveStatic = require('serve-static'),
        serve = serveStatic(opts.dirName),
        index = serveIndex(opts.dirName, {'icons': true}),
        acceptedImageExtensions = ['jpeg', 'jpg', 'png', 'gif'];

    app = express();
    app.use(busboy());

    app.get(['/dist/*'], function (req, res) {
        var done = finalhandler(req, res);
        serve(req, res, function onNext(err) {
            if (err) {
                return done(err);
            }
            index(req, res, done);
        });
    });

    app.get('/files*', function (req, res) {
        var done = finalhandler(req, res);
        serve(req, res, function onNext(err) {
            if (err) {
                return done(err);
            }
            index(req, res, done);
        });
    });

    // use bodyParser middleware for handling request bodies (express does *not* provide that feature out-of-the-box).
    // since we only have one case of that (POST to /login where username, password are in the body) and that one is url-encoded,
    // we only need that flavor of bodyParser. about the "extended" property, see https://github.com/expressjs/body-parser#bodyparserurlencodedoptions
    app.use(bodyParser.urlencoded({ extended: false }));
    // same for parsing cookie
    app.use(cookieParser());

    appLifeCycle && appLifeCycle.phase1 && appLifeCycle.phase1(app);
    app.get(/^((?!^(\/dist|\/bower_components)).)*$/, function(req, res, next) {

        if (packageJSON.config.auth) {
            // file request
            let isAuth = req.session && req.session.authId;
            if (!/\./.test(req.path) && !isAuth) {
                // TODO sending the login page only makes sense for browser requests. if anybody is e.g. using curl to
                // retrieve message bundles, we should only return a 401 but no content
                res.sendFile(__dirname + '/auth.html');
            } else {
                next();
            }
        } else {
            next();
        }

    });

    app.post('/uploadFile', function (req, res, next) {
        if (packageJSON.config.auth) {
            if (req.session && (req.session.isMaintainer) || req.session.isAdmin) {
                if (req.session.isAdmin) {
                    next();
                } else if (!/.json/.test(req.query.filename)) {
                    next();
                } else {
                    res.status(401).send('Not authorized');
                }
            } else {
                res.status(401).send('Not authorized');
            }
        } else {
            // res.status(401).send('Not authorized');
            next()
        }
    });

    /**
     * Limited restrictions!
     *
     * visitors:
     *  * are not allowed at all
     * maintainer:
     *  * not allowed to delete .json files
     * admins:
     *  * allowed to do everything
     */
    app.post('/deleteFile', function (req, res, next) {
        if (packageJSON.config.auth) {
            if (req.session && req.session.isMaintainer || req.session.isAdmin) {
                if (req.session.isAdmin) {
                    next();
                } else if (!/.json/.test(req.query.filename)) {
                    next();
                } else {
                    res.status(401).send('Not authorized');
                }
            } else {
                res.status(401).send('Not authorized');
            }
        } else {
            // res.status(401).send('Not authorized');
            next()
        }
    });
    /**
     * match except for folder dist
     *
     * If the URL has a dot inside it expect to send a files. Otherwise it sends the index.
     */
    app.get(/^((?!^(\/dist)).)*$/, function (req, res) {
        if (/\./.test(req.path)) {
            // contains a . - looks like a file request so check the files system
            fs.exists(decodeURI(opts.fileStorageName + req.path), function (exists) {
                if (exists) {
                    // not sure if it is good by default but - needs to be configurable
                    res.header("Access-Control-Allow-Origin", "*");
                    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

                    if (/\?tmb/.test(req.url)) {

                        thumbNail.create(decodeURI(req.path), function (file) {
                            if (file) {
                                res.sendFile(file);
                            } else {
                                res.sendFile(decodeURI(opts.fileStorageName + req.path));
                            }
                        });

                    } else {
                        res.sendFile(decodeURI(opts.fileStorageName + req.path), {dotfiles : 'allow'});
                    }
                } else {
                    // no file found - send 404 file
                    res.status(404).sendFile(opts.fourOFourFile ? opts.fourOFourFile : __dirname + '/404.html');
                }
            });

        } else {
            // send index
            res.sendFile(opts.dirName + 'index.html');

        }
    });

    app.post('/uploadFile', function (req, res) {
        var fstream, folder = folderUtil.formatFolder(req.query.folder);

        req.pipe(req.busboy);
        req.busboy.on('file', function (fieldname, file, filename) {
            // replace all spaces with underscores
            // TODO it's not a good idea to rename file - because there are people they put spaces in a file name
            var fName = filename; //.split(' ').join('_');

            function writeFile() {

                fstream = fs.createWriteStream(opts.fileStorageName + folder + fName);
                file.pipe(fstream);
                fstream.on('close', function () {
                    // TODO add correct type
                    var extension = fName.split('.').pop();
                    if (extension && acceptedImageExtensions.indexOf(extension.toLowerCase()) !== -1) {
                        res.status(200).send({file: folder + fName, name: fName, type: 'image/jpg'});
                    } else {
                        res.status(200).send({file: folder + fName, name: fName, type: extension});
                    }
                });
            }
            changeHistoryLogger.write(opts.fileStorageName, folder + fName, 'upload', req.session.authId || 'anonymous');
            appLifeCycle && appLifeCycle.onUploadFile && appLifeCycle.onUploadFile(req, {
                rootFolder : opts.fileStorageName,
                fileName : folder + fName
            });
            folderUtil.createFolder(opts.fileStorageName, folder, writeFile);
        });
    });

    /**
     * get all available files
     */
    app.post('/getFiles', function (req, res) {
        var folder = '';

        req.on("data", function (chunk) {
            folder += chunk.toString();
        });

        req.on("end", function () {
            folder = folderUtil.formatFolder(folder);
            fs.readdir(opts.fileStorageName + folder, function (err, files) {

                var fileList = [],
                    length;

                if (err === null) {
                    files = files.filter(function (fileName) {
                        return fileName.split('/').pop().startsWith('tmb_') ? undefined : fileName
                    });
                    if (appLifeCycle && appLifeCycle.fileFilter) {
                        files = files.filter(appLifeCycle.fileFilter);
                    }
                    length = files.length;
                    files.forEach(function (file) {
                        fs.stat(opts.fileStorageName + folder + file, function (err, stats) {
                            if (stats.isFile()) {
                                // TODO add correct type
                                var extension = file.split('.').pop();

                                if (extension && acceptedImageExtensions.indexOf(extension.toLowerCase()) !== -1) {
                                    fileList.push({file: folder + file, name: file, type: 'image/jpg'});
                                } else {
                                    fileList.push({file: folder + file, name: file, type: extension});
                                }
                            } else if (stats.isDirectory()) {
                                // filter out directories - if we need directories we should ask separately for it
                                console.log('Found a directory named:', file);
                            }
                            length--;
                            if (length <= 0) {
                                res.status(200).send(fileList);
                            }
                        });
                    });
                }
            });
        });
    });

    /**
     * get all available folders
     */
    app.post('/getFolders', function (req, res) {
        // get a list of all folders
        var folder = '';

        req.on("data", function (chunk) {
            folder += chunk.toString();
        });

        req.on("end", function () {
            folder = folderUtil.formatFolder(folder);
            fs.readdir(opts.fileStorageName + folder, function (err, files) {
                var fileList = [],
                    length;

                if (err === null) {
                    length = files.length;
                    files.forEach(function (file) {
                        fs.stat(opts.fileStorageName + folder + file, function (err, stats) {
                            if (err) {
                                console.log("app:path not exists:", err);
                                return;
                            }
                            if (stats.isDirectory()) {
                                fileList.push(file);
                            }
                            length--;
                            if (length <= 0) {
                                res.status(200).send(fileList);
                            }
                        });
                    });
                }
            });
        });
    });

    /**
     * delete a file
     */
    app.post('/deleteFile', function (req, res) {
        var fileName;
        if (req.query.hasOwnProperty('filename')) {
            fileName = req.query.filename;
            if (fileName[0] !== '/') {
                fileName = '/' + fileName;
            }
            fs.unlink(opts.fileStorageName + fileName, function () {
                changeHistoryLogger.write(opts.fileStorageName, fileName, 'delete', req.session.authId || 'anonymous');
                appLifeCycle && appLifeCycle.onDeleteFile && appLifeCycle.onDeleteFile(req, {
                    rootFolder : opts.fileStorageName,
                    fileName : fileName
                });
                res.status(200).send(req.query.filename);
            });
            thumbNail.remove(fileName);
        } else {
            res.status(200).send(false);
        }
    });

    let server;

    server = app.listen(opts.port, function () {
        console.log('server started on port %d', opts.port);
    });

    // initialize the json persist via websocket
    wsConnection(server, {
        secret : opts.secret,
        dirName : opts.fileStorageName
    });

    return app;
}

module.exports = main;<|endoftext|>


<commit_before>// This file specifically targets integration with the add-ons tab in Firefox
// 4+, thus it makes liberal use of features only available there.
//
// Derived from the SlipperyMonkey extension originally by Dave Townsend:
//   http://hg.oxymoronical.com/extensions/SlipperyMonkey/
//   http://www.oxymoronical.com/blog/2010/07/How-to-extend-the-new-Add-ons-Manager

// Module exported symbols.
var EXPORTED_SYMBOLS = ['addonsStartup'];

////////////////////////////////////////////////////////////////////////////////
// Module level imports / constants / globals.
////////////////////////////////////////////////////////////////////////////////

Components.utils.import('resource://gre/modules/AddonManager.jsm');
Components.utils.import('resource://gre/modules/Services.jsm');
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');

const Cc = Components.classes;
const Ci = Components.interfaces;
const NS_XHTML = 'http://www.w3.org/1999/xhtml';
const SCRIPT_ID_SUFFIX = '@greasespot.net';

// Pull this helper method into this module scope; it's not module-ized yet.
var GM_getConfig;
(function() {
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
    .getService(Components.interfaces.mozIJSSubScriptLoader);
var scope = {};
loader.loadSubScript('chrome://greasemonkey/content/utils.js', scope);
GM_getConfig = scope.GM_getConfig;
})();

////////////////////////////////////////////////////////////////////////////////
// Addons API Integration
////////////////////////////////////////////////////////////////////////////////

var AddonProvider = {
  getAddonByID: function(aId, aCallback) {
    aCallback(ScriptAddonFactoryById(aId));
  },

  getAddonsByTypes: function(aTypes, aCallback) {
    if (aTypes && aTypes.indexOf('user-script') < 0) {
      aCallback([]);
    } else {
      var scriptAddons = [];
      GM_getConfig().scripts.forEach(function(script) {
        scriptAddons.push(ScriptAddonFactoryByScript(script));
      });
      aCallback(scriptAddons);
    }
  }
};

var ScriptAddonCache = {};
function ScriptAddonFactoryByScript(aScript) {
  var id = aScript.id + SCRIPT_ID_SUFFIX;
  if (!(id in ScriptAddonCache)) {
    ScriptAddonCache[id] = new ScriptAddon(aScript);
  }
  return ScriptAddonCache[id];
}
function ScriptAddonFactoryById(aId) {
  var scripts = GM_getConfig().getMatchingScripts(
      function(script) {
        return (script.id + SCRIPT_ID_SUFFIX) == aId;
      });
  if (1 == scripts.length) return ScriptAddonFactoryByScript(scripts[0]);
  // TODO: throw an error instead?
  return null;
}

// https://developer.mozilla.org/en/Addons/Add-on_Manager/Addon
function ScriptAddon(aScript) {
  this._script = aScript;

  this.id = aScript.id + SCRIPT_ID_SUFFIX;
  this.name = this._script.name;
  this.version = this._script.version;
  this.description = this._script.description;
  this.iconURL = this._script.icon.fileURL;
  this.size = this._script.size;
  this.updateDate = this._script.modifiedDate;
}

// Required attributes.
ScriptAddon.prototype.id = null;
ScriptAddon.prototype.version = null;
ScriptAddon.prototype.type = 'user-script';
ScriptAddon.prototype.isCompatible = true;
ScriptAddon.prototype.providesUpdatesSecurely = true;
ScriptAddon.prototype.blocklistState = 0;
ScriptAddon.prototype.appDisabled = false;
ScriptAddon.prototype.scope = AddonManager.SCOPE_PROFILE;
ScriptAddon.prototype.name = null;
ScriptAddon.prototype.creator = null;
ScriptAddon.prototype.pendingOperations = 0;

// Optional attributes
ScriptAddon.prototype.description = null;
ScriptAddon.prototype.size = null;

// Private and custom attributes.
ScriptAddon.prototype._script = null;

ScriptAddon.prototype.__defineGetter__('executionIndex',
function ScriptAddon_prototype_getter_executionIndex() {
  dump('running executionIndex getter, for addon '+this.name+'\n');
  var val = GM_getConfig()._scripts.indexOf(this._script);
  dump('got val '+val+'\n');
  return val;
});

// Getters/setters/functions for API attributes.
ScriptAddon.prototype.__defineGetter__('isActive',
function ScriptAddon_prototype_getter_isActive() {
	return this._script.enabled;
});

ScriptAddon.prototype.__defineGetter__('userDisabled',
function ScriptAddon_prototype_getter_userDisabled() {
  return !this._script.enabled;
});

ScriptAddon.prototype.__defineSetter__('userDisabled',
function ScriptAddon_prototype_setter_userDisabled(val) {
  if (val == this.userDisabled) {
    return val;
  }

  AddonManagerPrivate.callAddonListeners(
      val ? 'onEnabling' : 'onDisabling', this, false);
  this._script.enabled = !val;
  AddonManagerPrivate.callAddonListeners(
      val ? 'onEnabled' : 'onDisabled', this);
});

ScriptAddon.prototype.__defineGetter__('permissions',
function ScriptAddon_prototype_getter_permissions() {
  var perms = AddonManager.PERM_CAN_UNINSTALL;
  perms |= this.userDisabled
      ? AddonManager.PERM_CAN_ENABLE
      : AddonManager.PERM_CAN_DISABLE;
  return perms;
});

ScriptAddon.prototype.isCompatibleWith = function() {
  return true;
};

ScriptAddon.prototype.findUpdates = function(aListener) {
  if ('onNoCompatibilityUpdateAvailable' in aListener) {
    aListener.onNoCompatibilityUpdateAvailable(this);
  }
  if ('onNoUpdateAvailable' in aListener) {
    aListener.onNoUpdateAvailable(this);
  }
  if ('onUpdateFinished' in aListener) {
    aListener.onUpdateFinished(this);
  }
};

ScriptAddon.prototype.uninstall = function() {
  AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
  // TODO: pick an appropriate time, and act on these pending uninstalls.
  this.pendingOperations |= AddonManager.PENDING_UNINSTALL;
  AddonManagerPrivate.callAddonListeners("onUninstalled", this);
};

ScriptAddon.prototype.cancelUninstall = function() {
  this.pendingOperations ^= AddonManager.PENDING_UNINSTALL;
  AddonManagerPrivate.callAddonListeners("onOperationCancelled", this);
};

////////////////////////////////////////////////////////////////////////////////

var WindowObserver = {
  // Inject the 'User Scripts' choice into the list of add-on types.
  addToAddonsManager: function(aWindow) {
    // This function used to handle tasks that are now done in a XUL overlay.
    // Leaving the function here in case the routing to make it run at the
    // right time proves useful.
    // TODO: Remove once Firefox 4 is final, if it is still unused.
  },

  findAllAddonsManagers: function() {
    var managers = [];
    var windows = Services.wm.getEnumerator('navigator:browser');
    while (windows.hasMoreElements()) {
      var window = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
      window.gBrowser.browsers.forEach(function(aBrowser) {
        if (aBrowser.currentURI.spec == 'about:addons')
          managers.push(aBrowser.contentWindow);
      });
    }
    return managers;
  },

  addToAddonsManagers: function() {
    var managers = this.findAllAddonsManagers();
    managers.forEach(function(aWindow) {
      this.addToAddonsManager(aWindow);
    }, this);
  },

  /* TODO: restore when we are restartless for FF4.
  removeFromAddonsManagers: function() {
    var managers = this.findAllAddonsManagers();
    managers.forEach(function(aWindow) {
      var window = aWindow.wrappedJSObject;
      var scripts = window.document.getElementById('category-scripts');
      scripts.parentNode.removeChild(scripts);
      var styles = window.document.getElementById('script-styles');
      styles.parentNode.removeChild(styles);
      window.gStrings.ext = window.gStrings.ext.basebundle;
    });
  },
  */

  observe: function(aSubject, aTopic, aData) {
    var win = aSubject;
    var uri = win.document.documentURIObject;
    if (uri.spec != 'about:addons') return;
    // Run after DOM load, so that the window contents exist, to be altered.
    win.addEventListener('DOMContentLoaded',
        function() { WindowObserver.addToAddonsManager(win); },
        false);
  }
};

////////////////////////////////////////////////////////////////////////////////

var _addonsStartupHasRun = false;
function addonsStartup(aParams) {
  if (_addonsStartupHasRun) return;
  _addonsStartupHasRun = true;

  Services.obs.addObserver(WindowObserver, 'chrome-document-global-created', false);
  AddonManagerPrivate.registerProvider(AddonProvider);
  WindowObserver.addToAddonsManagers();
}

/* TODO: restore when we are restartless for FF4.
function addonsShutdown() {
  WindowObserver.removeFromAddonsManagers();
  AddonManagerPrivate.unregisterProvider(AddonProvider);
  Services.obs.removeObserver(WindowObserver, 'chrome-document-global-created');
}
*/
<commit_msg>Minor cleanups.<commit_after>// This file specifically targets integration with the add-ons tab in Firefox
// 4+, thus it makes liberal use of features only available there.
//
// Derived from the SlipperyMonkey extension originally by Dave Townsend:
//   http://hg.oxymoronical.com/extensions/SlipperyMonkey/
//   http://www.oxymoronical.com/blog/2010/07/How-to-extend-the-new-Add-ons-Manager

// Module exported symbols.
var EXPORTED_SYMBOLS = ['addonsStartup'];

////////////////////////////////////////////////////////////////////////////////
// Module level imports / constants / globals.
////////////////////////////////////////////////////////////////////////////////

Components.utils.import('resource://gre/modules/AddonManager.jsm');
Components.utils.import('resource://gre/modules/Services.jsm');
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');

const Cc = Components.classes;
const Ci = Components.interfaces;
const NS_XHTML = 'http://www.w3.org/1999/xhtml';
const SCRIPT_ID_SUFFIX = '@greasespot.net';

// Pull this helper method into this module scope; it's not module-ized yet.
var GM_getConfig;
(function() {
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
    .getService(Components.interfaces.mozIJSSubScriptLoader);
var scope = {};
loader.loadSubScript('chrome://greasemonkey/content/utils.js', scope);
GM_getConfig = scope.GM_getConfig;
})();

////////////////////////////////////////////////////////////////////////////////
// Addons API Integration
////////////////////////////////////////////////////////////////////////////////

var AddonProvider = {
  getAddonByID: function(aId, aCallback) {
    aCallback(ScriptAddonFactoryById(aId));
  },

  getAddonsByTypes: function(aTypes, aCallback) {
    if (aTypes && aTypes.indexOf('user-script') < 0) {
      aCallback([]);
    } else {
      var scriptAddons = [];
      GM_getConfig().scripts.forEach(function(script) {
        scriptAddons.push(ScriptAddonFactoryByScript(script));
      });
      aCallback(scriptAddons);
    }
  }
};

var ScriptAddonCache = {};
function ScriptAddonFactoryByScript(aScript) {
  var id = aScript.id + SCRIPT_ID_SUFFIX;
  if (!(id in ScriptAddonCache)) {
    ScriptAddonCache[id] = new ScriptAddon(aScript);
  }
  return ScriptAddonCache[id];
}
function ScriptAddonFactoryById(aId) {
  var scripts = GM_getConfig().getMatchingScripts(
      function(script) {
        return (script.id + SCRIPT_ID_SUFFIX) == aId;
      });
  if (1 == scripts.length) return ScriptAddonFactoryByScript(scripts[0]);
  // TODO: throw an error instead?
  return null;
}

// https://developer.mozilla.org/en/Addons/Add-on_Manager/Addon
function ScriptAddon(aScript) {
  this._script = aScript;

  this.id = aScript.id + SCRIPT_ID_SUFFIX;
  this.name = this._script.name;
  this.version = this._script.version;
  this.description = this._script.description;
  this.iconURL = this._script.icon.fileURL;
  this.size = this._script.size;
  this.updateDate = this._script.modifiedDate;
}

// Required attributes.
ScriptAddon.prototype.id = null;
ScriptAddon.prototype.version = null;
ScriptAddon.prototype.type = 'user-script';
ScriptAddon.prototype.isCompatible = true;
ScriptAddon.prototype.providesUpdatesSecurely = true;
ScriptAddon.prototype.blocklistState = 0;
ScriptAddon.prototype.appDisabled = false;
ScriptAddon.prototype.scope = AddonManager.SCOPE_PROFILE;
ScriptAddon.prototype.name = null;
ScriptAddon.prototype.creator = null;
ScriptAddon.prototype.pendingOperations = 0;

// Optional attributes
ScriptAddon.prototype.description = null;
ScriptAddon.prototype.size = null;

// Private and custom attributes.
ScriptAddon.prototype._script = null;

ScriptAddon.prototype.__defineGetter__('executionIndex',
function ScriptAddon_prototype_getter_executionIndex() {
  return GM_getConfig()._scripts.indexOf(this._script);
});

// Getters/setters/functions for API attributes.
ScriptAddon.prototype.__defineGetter__('isActive',
function ScriptAddon_prototype_getter_isActive() {
  return this._script.enabled;
});

ScriptAddon.prototype.__defineGetter__('userDisabled',
function ScriptAddon_prototype_getter_userDisabled() {
  return !this._script.enabled;
});

ScriptAddon.prototype.__defineSetter__('userDisabled',
function ScriptAddon_prototype_setter_userDisabled(val) {
  if (val == this.userDisabled) {
    return val;
  }

  AddonManagerPrivate.callAddonListeners(
      val ? 'onEnabling' : 'onDisabling', this, false);
  this._script.enabled = !val;
  AddonManagerPrivate.callAddonListeners(
      val ? 'onEnabled' : 'onDisabled', this);
});

ScriptAddon.prototype.__defineGetter__('permissions',
function ScriptAddon_prototype_getter_permissions() {
  var perms = AddonManager.PERM_CAN_UNINSTALL;
  perms |= this.userDisabled
      ? AddonManager.PERM_CAN_ENABLE
      : AddonManager.PERM_CAN_DISABLE;
  return perms;
});

ScriptAddon.prototype.isCompatibleWith = function() {
  return true;
};

ScriptAddon.prototype.findUpdates = function(aListener) {
  if ('onNoCompatibilityUpdateAvailable' in aListener) {
    aListener.onNoCompatibilityUpdateAvailable(this);
  }
  if ('onNoUpdateAvailable' in aListener) {
    aListener.onNoUpdateAvailable(this);
  }
  if ('onUpdateFinished' in aListener) {
    aListener.onUpdateFinished(this);
  }
};

ScriptAddon.prototype.uninstall = function() {
  AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
  // TODO: pick an appropriate time, and act on these pending uninstalls.
  this.pendingOperations |= AddonManager.PENDING_UNINSTALL;
  AddonManagerPrivate.callAddonListeners("onUninstalled", this);
};

ScriptAddon.prototype.cancelUninstall = function() {
  this.pendingOperations ^= AddonManager.PENDING_UNINSTALL;
  AddonManagerPrivate.callAddonListeners("onOperationCancelled", this);
};

////////////////////////////////////////////////////////////////////////////////

var WindowObserver = {
  // Inject the 'User Scripts' choice into the list of add-on types.
  addToAddonsManager: function(aWindow) {
    // This function used to handle tasks that are now done in a XUL overlay.
    // Leaving the function here in case the routing to make it run at the
    // right time proves useful.
    // TODO: Remove once Firefox 4 is final, if it is still unused.
  },

  findAllAddonsManagers: function() {
    var managers = [];
    var windows = Services.wm.getEnumerator('navigator:browser');
    while (windows.hasMoreElements()) {
      var window = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
      window.gBrowser.browsers.forEach(function(aBrowser) {
        if (aBrowser.currentURI.spec == 'about:addons')
          managers.push(aBrowser.contentWindow);
      });
    }
    return managers;
  },

  addToAddonsManagers: function() {
    var managers = this.findAllAddonsManagers();
    managers.forEach(function(aWindow) {
      this.addToAddonsManager(aWindow);
    }, this);
  },

  /* TODO: restore when we are restartless for FF4.
  removeFromAddonsManagers: function() {
    var managers = this.findAllAddonsManagers();
    managers.forEach(function(aWindow) {
      var window = aWindow.wrappedJSObject;
      var scripts = window.document.getElementById('category-scripts');
      scripts.parentNode.removeChild(scripts);
      var styles = window.document.getElementById('script-styles');
      styles.parentNode.removeChild(styles);
      window.gStrings.ext = window.gStrings.ext.basebundle;
    });
  },
  */

  observe: function(aSubject, aTopic, aData) {
    var win = aSubject;
    var uri = win.document.documentURIObject;
    if (uri.spec != 'about:addons') return;
    // Run after DOM load, so that the window contents exist, to be altered.
    win.addEventListener('DOMContentLoaded',
        function() { WindowObserver.addToAddonsManager(win); },
        false);
  }
};

////////////////////////////////////////////////////////////////////////////////

var _addonsStartupHasRun = false;
function addonsStartup(aParams) {
  if (_addonsStartupHasRun) return;
  _addonsStartupHasRun = true;

  Services.obs.addObserver(WindowObserver, 'chrome-document-global-created', false);
  AddonManagerPrivate.registerProvider(AddonProvider);
  WindowObserver.addToAddonsManagers();
}

/* TODO: restore when we are restartless for FF4.
function addonsShutdown() {
  WindowObserver.removeFromAddonsManagers();
  AddonManagerPrivate.unregisterProvider(AddonProvider);
  Services.obs.removeObserver(WindowObserver, 'chrome-document-global-created');
}
*/
<|endoftext|>


<commit_before>var expect = require('chai').expect;

describe('Requester Spec: timings', function () {
    var testrun,
        URL = 'http://postman-echo.com/get',
        collection = {
            item: [{
                request: {
                    url: URL,
                    method: 'GET'
                }
            }]
        };

    describe('with timings: undefined', function () {
        before(function (done) {
            this.run({
                collection: collection
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should include timing information by default', function () {
            var response = testrun.response.getCall(0).args[2];

            expect(response).to.have.property('timings');
            expect(response.timings).to.be.an('object').that.have.all.keys([
                'start',
                'socket',
                'lookup',
                'connect',
                'response',
                'end'
            ]);
        });
    });

    describe('with timings: true', function () {
        before(function (done) {
            this.run({
                requester: {
                    timings: true
                },
                collection: collection
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should include timing information', function () {
            var response = testrun.response.getCall(0).args[2];

            expect(response).to.have.property('timings');
            expect(response.timings).to.be.an('object').that.have.all.keys([
                'start',
                'socket',
                'lookup',
                'connect',
                'response',
                'end'
            ]);
        });
    });

    describe('with timings: false', function () {
        before(function (done) {
            this.run({
                requester: {
                    timings: false
                },
                collection: collection
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should not include timing information', function () {
            var response = testrun.response.getCall(0).args[2];

            expect(response).to.not.have.property('timings');
        });
    });
});
<commit_msg>Minor grammer change in timing.test.js<commit_after>var expect = require('chai').expect;

describe('Requester Spec: timings', function () {
    var testrun,
        URL = 'http://postman-echo.com/get',
        collection = {
            item: [{
                request: {
                    url: URL,
                    method: 'GET'
                }
            }]
        };

    describe('with timings: undefined', function () {
        before(function (done) {
            this.run({
                collection: collection
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should include timing information by default', function () {
            var response = testrun.response.getCall(0).args[2];

            expect(response).to.have.property('timings');
            expect(response.timings).to.be.an('object').that.has.all.keys([
                'start',
                'socket',
                'lookup',
                'connect',
                'response',
                'end'
            ]);
        });
    });

    describe('with timings: true', function () {
        before(function (done) {
            this.run({
                requester: {
                    timings: true
                },
                collection: collection
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should include timing information', function () {
            var response = testrun.response.getCall(0).args[2];

            expect(response).to.have.property('timings');
            expect(response.timings).to.be.an('object').that.has.all.keys([
                'start',
                'socket',
                'lookup',
                'connect',
                'response',
                'end'
            ]);
        });
    });

    describe('with timings: false', function () {
        before(function (done) {
            this.run({
                requester: {
                    timings: false
                },
                collection: collection
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should not include timing information', function () {
            var response = testrun.response.getCall(0).args[2];

            expect(response).to.not.have.property('timings');
        });
    });
});
<|endoftext|>


<commit_before>/** Use the Tab key to jump out of groupings after closing characters ", ', ), ] and } like in Eclipse. */
define(function (require, exports, module) {
    'use strict';

    var CommandManager = brackets.getModule('command/CommandManager');
    var KeyBindingManager = brackets.getModule('command/KeyBindingManager');
    var EditorManager = brackets.getModule('editor/EditorManager');

    function tabOutIfPossible() {
        var editor = EditorManager.getFocusedEditor();
        if (! editor)
            return;

        var currentCursorPosition = editor.getCursorPos();
        var nextCursorPosition = {line: currentCursorPosition.line, ch: currentCursorPosition.ch + 1}

        var nextCharacter = editor.document.getRange(currentCursorPosition, nextCursorPosition);
        var closingCharacters = ['"', "'", ')', ']', '}'];
        var nextCharacterIsNotClosingCharacter = closingCharacters.indexOf(nextCharacter) === -1;
        if (nextCharacterIsNotClosingCharacter)
            return true;

        var beginningOfLinePosition = {line: currentCursorPosition.line, ch: 0};
        var textInLineBeforeCursor = editor.document.getRange(beginningOfLinePosition, currentCursorPosition);
        var hasOnlyWhitespaceToTheLeft = textInLineBeforeCursor.trim() === '';
        if (hasOnlyWhitespaceToTheLeft)
            return true;

        editor.setCursorPos(nextCursorPosition);

        return false;
    }

    var MY_COMMAND_ID = 'dag0310.tab-out';

    CommandManager.register('Tab Out', MY_COMMAND_ID, tabOutIfPossible);

    KeyBindingManager.addBinding(MY_COMMAND_ID, 'Tab');
});
<commit_msg>Bugfix: Do not apply if there is selected text<commit_after>/** Use the Tab key to jump out of groupings after closing characters ", ', ), ] and } like in Eclipse. */
define(function (require, exports, module) {
    'use strict';

    var CommandManager = brackets.getModule('command/CommandManager');
    var KeyBindingManager = brackets.getModule('command/KeyBindingManager');
    var EditorManager = brackets.getModule('editor/EditorManager');

    function tabOutIfPossible() {
        var editor = EditorManager.getFocusedEditor();
        if (! editor)
            return;

        var currentCursorPosition = editor.getCursorPos();
        var nextCursorPosition = {line: currentCursorPosition.line, ch: currentCursorPosition.ch + 1}

        if (editor.getSelectedText() !== '')
            return true;

        var nextCharacter = editor.document.getRange(currentCursorPosition, nextCursorPosition);
        var closingCharacters = ['"', "'", ')', ']', '}'];
        var nextCharacterIsNotClosingCharacter = closingCharacters.indexOf(nextCharacter) === -1;
        if (nextCharacterIsNotClosingCharacter)
            return true;

        var beginningOfLinePosition = {line: currentCursorPosition.line, ch: 0};
        var textInLineBeforeCursor = editor.document.getRange(beginningOfLinePosition, currentCursorPosition);
        var hasOnlyWhitespaceToTheLeft = textInLineBeforeCursor.trim() === '';
        if (hasOnlyWhitespaceToTheLeft)
            return true;

        editor.setCursorPos(nextCursorPosition);

        return false;
    }

    var MY_COMMAND_ID = 'dag0310.tab-out';

    CommandManager.register('Tab Out', MY_COMMAND_ID, tabOutIfPossible);

    KeyBindingManager.addBinding(MY_COMMAND_ID, 'Tab');
});
<|endoftext|>


<commit_before>
// TokenList
// TokenList constructor to emulate classList property. The get fn should
// take the arguments (node), and return a string of tokens. The set fn
// should take the arguments (node, string).

//var SVGElement  = window.SVGElement;
//
//function TokenList(node, get, set) {
//	this.node = node;
//	this.get = get;
//	this.set = set;
//}
//
//TokenList.prototype = {
//	add: function() {
//		var n = arguments.length;
//		var tokens = this.get(this.node);
//		var array = tokens ? tokens.trim().split(rspaces) : [] ;
//
//		while (n--) {
//			if (array.indexOf(arguments[n]) === -1) {
//				array.push(arguments[n]);
//			}
//		}
//
//		this.set(this.node, array.join(' '));
//	},
//
//	remove: function() {
//		var n = arguments.length;
//		var tokens = this.get(this.node);
//		var array = tokens ? tokens.trim().split(rspaces) : [] ;
//		var i;
//
//		while (n--) {
//			i = array.indexOf(arguments[n]);
//			if (i !== -1) { array.splice(i, 1); }
//		}
//
//		this.set(this.node, array.join(' '));
//	},
//
//	contains: function(string) {
//		var tokens = this.get(this.node);
//		var array = tokens ? tokens.trim().split(rspaces) : [] ;
//		return array.indexOf(string) !== -1;
//	}
//};
//
//function setClass(node, classes) {
//	if (node instanceof SVGElement) {
//		node.setAttribute('class', classes);
//	}
//	else {
//		node.className = classes;
//	}
//}
//
//export function classes(node) {
//	return node.classList || new TokenList(node, function(node) {
//		return node.getAttribute('class');
//	}, setClass);
//}

import { get } from '../../fn/fn.js';

export const classes = get('classList');

export function addClass(string, node) {
	classes(node).add(string);
}

export function removeClass(string, node) {
	classes(node).remove(string);
}

export function frameClass(string, node) {
	var list = classes(node);
	list.add(string);
	requestAnimationFrame(function() {
		list.remove(string);
	});
}
<commit_msg>frameClass now holds class for 2 frames<commit_after>
// TokenList
// TokenList constructor to emulate classList property. The get fn should
// take the arguments (node), and return a string of tokens. The set fn
// should take the arguments (node, string).

//var SVGElement  = window.SVGElement;
//
//function TokenList(node, get, set) {
//	this.node = node;
//	this.get = get;
//	this.set = set;
//}
//
//TokenList.prototype = {
//	add: function() {
//		var n = arguments.length;
//		var tokens = this.get(this.node);
//		var array = tokens ? tokens.trim().split(rspaces) : [] ;
//
//		while (n--) {
//			if (array.indexOf(arguments[n]) === -1) {
//				array.push(arguments[n]);
//			}
//		}
//
//		this.set(this.node, array.join(' '));
//	},
//
//	remove: function() {
//		var n = arguments.length;
//		var tokens = this.get(this.node);
//		var array = tokens ? tokens.trim().split(rspaces) : [] ;
//		var i;
//
//		while (n--) {
//			i = array.indexOf(arguments[n]);
//			if (i !== -1) { array.splice(i, 1); }
//		}
//
//		this.set(this.node, array.join(' '));
//	},
//
//	contains: function(string) {
//		var tokens = this.get(this.node);
//		var array = tokens ? tokens.trim().split(rspaces) : [] ;
//		return array.indexOf(string) !== -1;
//	}
//};
//
//function setClass(node, classes) {
//	if (node instanceof SVGElement) {
//		node.setAttribute('class', classes);
//	}
//	else {
//		node.className = classes;
//	}
//}
//
//export function classes(node) {
//	return node.classList || new TokenList(node, function(node) {
//		return node.getAttribute('class');
//	}, setClass);
//}

import { get } from '../../fn/fn.js';

export const classes = get('classList');

export function addClass(string, node) {
	classes(node).add(string);
}

export function removeClass(string, node) {
	classes(node).remove(string);
}

function requestFrame(n, fn) {
	// Requst frames until n is 0, then call fn
	(function frame(t) {
		return n-- ?
			requestAnimationFrame(frame) :
			fn(t);
	})();
}

export function frameClass(string, node) {
	var list = classes(node);
	list.add(string);

	// Chrome (at least) requires 2 frames - I guess in the first, the
	// change is painted so we have to wait for the second to undo
	requestFrame(2, () => list.remove(string));
}
<|endoftext|>


<commit_before>/**
 * Created by truthlighting on 9/14/2016.
 */
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleTower = require('role.tower');
var roleHauler = require('role.hauler');

if (!Memory.hCreepID) {
    Memory.hCreepID = 1;
}
if (!Memory.bCreepID) {
    Memory.bCreepID = 1;
}
if (!Memory.uCreepID) {
    Memory.uCreepID = 1;
}
if (!Memory.cCreepID) {
    Memory.cCreepID = 1;
}

module.exports.loop = function () {

    for(var name in Memory.creeps) {
        if(!Game.creeps[name]) {
            delete Memory.creeps[name];
            console.log('Clearing non-existing creep memory:', name);
        }
    }

    var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
//    console.log('Harvesters: ' + harvesters.length);
    var sources = Game.rooms['W2N48'].find(FIND_SOURCES);
    var harvesterSources = _.map(Game.creeps, 'memory.assignedSource');
    var result;
    for (var i=0, l=sources.length; i < l, i++) {
        if (harvesterSources.indexOf(array[i]) == -1) { result = array[i]; break; }
    }
    console.log(result);

    if(harvesters.length < 2 && Game.spawns['Harmony'].canCreateCreep([WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE], "H-" + Memory.hCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE], "H-" + Memory.hCreepID, {role: 'harvester'});
        Memory.hCreepID++;
        console.log('Spawning new harvester: ' + newName);
    }

    var haulers = _.filter(Game.creeps, (creep) => creep.memory.role == 'hauler');

    if(haulers.length < 1 && Game.spawns['Harmony'].canCreateCreep([CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE], "C-" + Memory.cCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE], "C-" + Memory.cCreepID, {role: 'hauler'});
        Memory.cCreepID++;
        console.log('Spawning new hauler: ' + newName);
    }

    var upgraders = _.filter(Game.creeps, (creep) => creep.memory.role == 'upgrader');
//    console.log('Upgraders: ' + harvesters.length);

    if(upgraders.length < 4 && harvesters.length >= 2 && Game.spawns['Harmony'].canCreateCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "U-" + Memory.uCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "U-" + Memory.uCreepID, {role: 'upgrader' });
        Memory.uCreepID++;
        console.log('Spawning new upgrader: ' + newName);
    }

    var builders = _.filter(Game.creeps, (creep) => creep.memory.role == 'builder');
//    console.log('Upgraders: ' + harvesters.length);

    if(builders.length < 3 && harvesters.length >= 2 && Game.spawns['Harmony'].canCreateCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "B-" + Memory.bCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "B-" + Memory.bCreepID, {role: 'builder'});
        Memory.bCreepID++;
        console.log('Spawning new builder: ' + newName);
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        if(creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
        if(creep.memory.role == 'hauler') {
            roleHauler.run(creep);
        }
    }

    roleTower.run();
};<commit_msg>debugging new code for harvesters to assign them to a source<commit_after>/**
 * Created by truthlighting on 9/14/2016.
 */
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleTower = require('role.tower');
var roleHauler = require('role.hauler');

if (!Memory.hCreepID) {
    Memory.hCreepID = 1;
}
if (!Memory.bCreepID) {
    Memory.bCreepID = 1;
}
if (!Memory.uCreepID) {
    Memory.uCreepID = 1;
}
if (!Memory.cCreepID) {
    Memory.cCreepID = 1;
}

module.exports.loop = function () {

    for(var name in Memory.creeps) {
        if(!Game.creeps[name]) {
            delete Memory.creeps[name];
            console.log('Clearing non-existing creep memory:', name);
        }
    }

    var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
//    console.log('Harvesters: ' + harvesters.length);
    var sources = Game.rooms['W2N48'].find(FIND_SOURCES);
    var harvesterSources = _.map(Game.creeps, 'memory.assignedSource');
    var result;
    for (var i=0, l=sources.length; i < l; i++) {
        if (harvesterSources.indexOf(array[i]) == -1) { result = array[i]; break; }
    }
    console.log(result);

    if(harvesters.length < 2 && Game.spawns['Harmony'].canCreateCreep([WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE], "H-" + Memory.hCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE], "H-" + Memory.hCreepID, {role: 'harvester'});
        Memory.hCreepID++;
        console.log('Spawning new harvester: ' + newName);
    }

    var haulers = _.filter(Game.creeps, (creep) => creep.memory.role == 'hauler');

    if(haulers.length < 1 && Game.spawns['Harmony'].canCreateCreep([CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE,MOVE], "C-" + Memory.cCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE, MOVE], "C-" + Memory.cCreepID, {role: 'hauler'});
        Memory.cCreepID++;
        console.log('Spawning new hauler: ' + newName);
    }

    var upgraders = _.filter(Game.creeps, (creep) => creep.memory.role == 'upgrader');
//    console.log('Upgraders: ' + harvesters.length);

    if(upgraders.length < 4 && harvesters.length >= 2 && Game.spawns['Harmony'].canCreateCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "U-" + Memory.uCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "U-" + Memory.uCreepID, {role: 'upgrader' });
        Memory.uCreepID++;
        console.log('Spawning new upgrader: ' + newName);
    }

    var builders = _.filter(Game.creeps, (creep) => creep.memory.role == 'builder');
//    console.log('Upgraders: ' + harvesters.length);

    if(builders.length < 3 && harvesters.length >= 2 && Game.spawns['Harmony'].canCreateCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "B-" + Memory.bCreepID)==OK) {
        var newName = Game.spawns['Harmony'].createCreep([WORK,WORK,WORK,WORK,WORK,CARRY,CARRY,CARRY,MOVE,MOVE,MOVE], "B-" + Memory.bCreepID, {role: 'builder'});
        Memory.bCreepID++;
        console.log('Spawning new builder: ' + newName);
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        if(creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
        if(creep.memory.role == 'hauler') {
            roleHauler.run(creep);
        }
    }

    roleTower.run();
};<|endoftext|>


<commit_before>
'use strict';

const ava = require('ava'),
  restHalTestTools = require('../'),
  superTest = require('supertest');

ava("resourceImplementOptionsMethod fail if agent not provided", (t) => {
  t.throws(() => {
    let testContext = { context: {} };

    restHalTestTools.resourceImplementOptionsMethod(testContext);
  }, 'Cannot read property \'options\' of undefined');
});

ava("resourceImplementOptionsMethod fail if resource not provided", (t) => {
  t.throws(() => {
    let testContext = { context: {
      agent: superTest('http://some.api')
    } };

    restHalTestTools.resourceImplementOptionsMethod(testContext);
  }, 'undefined');
});
<commit_msg>Added tests for the resourceImplementOptionsMethod function<commit_after>
'use strict';

const ava = require('ava'),
  restHalTestTools = require('../'),
  superTest = require('supertest');

ava("resourceImplementOptionsMethod fail if agent not provided", (t) => {
  let testContext = { context: {} };

  t.throws(
    restHalTestTools.resourceImplementOptionsMethod.bind(null, testContext),
    'Cannot read property \'options\' of undefined'
  );
});

ava("resourceImplementOptionsMethod fail if resource not provided", (t) => {
  let testContext = { context: {
    agent: superTest('http://some.api')
  } };

  t.throws(
    restHalTestTools.resourceImplementOptionsMethod.bind(null, testContext),
    'undefined'
  );
});

ava("resourceImplementOptionsMethod fail if status is not 200", (t) => {
  function handler(_, res){
    res.statusCode = 300;
    res.end();
  }

  let testContext = { context: {
    resource: "/",
    agent: superTest(handler)
  } };

  restHalTestTools.resourceImplementOptionsMethod(testContext)
    .end((res) => { t.ifError(res); });
});

ava("resourceImplementOptionsMethod succeed if status is 200", (t) => {
  function handler(_, res){
    res.statusCode = 200;
    res.end();
  }

  let testContext = { context: {
    resource: "/",
    agent: superTest(handler)
  } };

  restHalTestTools.resourceImplementOptionsMethod(testContext)
    .end((res) => { t.is(res, null); });
});
<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, $, brackets, window */

/** Extension that starts/stops Recode and saves when appropriate */
define(function (require, exports, module) {
    "use strict";

    var CommandManager = brackets.getModule('command/CommandManager'),
        Menus = brackets.getModule('command/Menus'),
        MainViewManager = brackets.getModule('view/MainViewManager'),
        DocumentManager = brackets.getModule('document/DocumentManager'),
        FileSystem = brackets.getModule('filesystem/FileSystem');

    var Recoder = function() {
        this.currentDocument = null;
        this.recording = false;
        this.saveDir = null;
    };

    Recoder.prototype.onFileChange = function(e, newFile, newPaneId, oldFile, oldPaneId) {
        this.removeDocument();
        this.addDocument();
    };

    Recoder.prototype.onTextChange = function(e, document, changelist) {
        console.log(changelist);
    };

    Recoder.prototype.addDocument = function() {
        this.currentDocument = DocumentManager.getCurrentDocument();
        if (this.currentDocument) {
            this.currentDocument.addRef();
            this.currentDocument.on('change', this.onTextChange);
        }
    };

    Recoder.prototype.removeDocument = function() {
        if (this.currentDocument) {
            this.currentDocument.off('change', this.onTextChange);
            this.currentDocument.releaseRef();
        }
        this.currentDocument = null;
    };

    Recoder.prototype.start = function() {
        var self = this;
        FileSystem.showOpenDialog(false, true, "Choose a folder to save in", '', null, function(error, files) {
            if ((error) || (files.length < 1)) {
                // Do something about this
                return;
            }
            FileSystem.resolve(files[0], function(error, entry, stats) {
                if ((error) || (!stats.isDirectory)) {
                    // Do something about this
                    return
                }
                self.recording = true;
                self.saveDir = entry.fullPath;

                MainViewManager.on('currentFileChange', self.onFileChange);
                self.addDocument();
            });
        });
    };

    Recoder.prototype.stop = function() {
        this.recording = false;

        // Unbind events
        MainViewManager.off('currentFileChange', this.onFileChange);
        this.removeDocument();
    };

    var recoder = new Recoder();

    // Function to run when the menu item is clicked
    function handleRecode() {
        if (!recoder.recording) {
            recoder.start();
            command.setName('Stop Recoding');
        } else {
            recoder.stop();
            command.setName('Recode');
        }
    }

    // First, register a command - a UI-less object associating an id to a handler
    var RECODE_COMMAND_ID = "recode.recode";   // package-style naming to avoid collisions
    var command = CommandManager.register("Recode", RECODE_COMMAND_ID, handleRecode);

    // Then create a menu item bound to the command
    // The label of the menu item is the name we gave the command (see above)
    var menu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU);
    menu.addMenuItem(RECODE_COMMAND_ID);

    // We could also add a key binding at the same time:
    //menu.addMenuItem(MY_COMMAND_ID, "Ctrl-Alt-H");
    // (Note: "Ctrl" is automatically mapped to "Cmd" on Mac)
});
<commit_msg>Add automatic folder creation at project root<commit_after>/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, $, brackets, window */

/** Extension that starts/stops Recode and saves when appropriate */
define(function (require, exports, module) {
    "use strict";

    var CommandManager = brackets.getModule('command/CommandManager'),
        Menus = brackets.getModule('command/Menus'),
        MainViewManager = brackets.getModule('view/MainViewManager'),
        DocumentManager = brackets.getModule('document/DocumentManager'),
        FileSystem = brackets.getModule('filesystem/FileSystem'),
        ProjectManager = brackets.getModule('project/ProjectManager'),
        Dialogs = brackets.getModule('widgets/Dialogs'),
        DefaultDialogs = brackets.getModule('widgets/DefaultDialogs');

    var Recoder = function() {
        this.currentDocument = null;
        this.recording = false;
        this.saveDir = null;
        this.startTime = null;
    };

    Recoder.prototype.onFileChange = function(e, newFile, newPaneId, oldFile, oldPaneId) {
        this.removeDocument();
        this.addDocument();
    };

    Recoder.prototype.onTextChange = function(e, document, changelist) {
        console.log(changelist);
    };

    Recoder.prototype.addDocument = function() {
        this.currentDocument = DocumentManager.getCurrentDocument();
        if (this.currentDocument) {
            this.currentDocument.addRef();
            this.currentDocument.on('change', this.onTextChange);
        }
    };

    Recoder.prototype.removeDocument = function() {
        if (this.currentDocument) {
            this.currentDocument.off('change', this.onTextChange);
            this.currentDocument.releaseRef();
        }
        this.currentDocument = null;
    };

    Recoder.prototype.start = function(callback) {
        var self = this;
        var now = new Date();
        var formatDate = (now.getFullYear()) + '-' + (now.getMonth() + 1) + '-' + (now.getDate()) + '_' + (now.getHours()) + '-' + (now.getMinutes()) + '-' + (now.getSeconds());
        var recodeFolder = ProjectManager.getProjectRoot().fullPath + 'recode-sessions/';

        var startRecode = function startRecode() {
            self.recording = true;

            MainViewManager.on('currentFileChange', self.onFileChange);
            self.addDocument();

            callback();
        };

        var makeDirectory = function makeDirectory() {
            self.startTime = now.getTime();
            self.saveDir = recodeFolder + formatDate + '/';
            console.log(self.saveDir);

            ProjectManager
                .createNewItem(ProjectManager.getProjectRoot(), 'recode-sessions/' + formatDate + '/', true, true);
                .done(startRecode);
        };

        FileSystem.resolve(recodeFolder, function(error, file, stats) {
            if ((error) && (error !== 'NotFound')) {
                Dialogs.showModalDialog(DefaultDialogs.DIALOG_ID_ERROR, 'Error', 'Something went wrong when trying to find the recode-sessions folder: ' + error);
                return;
            }

            if (file.isDirectory) {
                makeDirectory();
            } else {
                Dialogs.showModalDialog(DefaultDialogs.DIALOG_ID_ERROR, 'Save Error', 'The entry "recode-sessions" at project root must be a directory, currently it is not.');
            }
        });
    };

    Recoder.prototype.stop = function() {
        this.recording = false;

        // Unbind events
        MainViewManager.off('currentFileChange', this.onFileChange);
        this.removeDocument();
    };

    var recoder = new Recoder();

    // Function to run when the menu item is clicked
    function handleRecode() {
        if (!recoder.recording) {
            recoder.start(function() {
                command.setName('Stop Recoding');
            });
        } else {
            recoder.stop();
            command.setName('Recode');
        }
    }

    // First, register a command - a UI-less object associating an id to a handler
    var RECODE_COMMAND_ID = "recode.recode";   // package-style naming to avoid collisions
    var command = CommandManager.register("Recode", RECODE_COMMAND_ID, handleRecode);

    // Then create a menu item bound to the command
    // The label of the menu item is the name we gave the command (see above)
    var menu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU);
    menu.addMenuItem(RECODE_COMMAND_ID);

    // We could also add a key binding at the same time:
    //menu.addMenuItem(MY_COMMAND_ID, "Ctrl-Alt-H");
    // (Note: "Ctrl" is automatically mapped to "Cmd" on Mac)
});
<|endoftext|>