<commit_before>'use strict';
const Readline = require('@serialport/parser-readline'); // modify
const Delimiter = require('@serialport/parser-delimiter');
const SerialPort = require('@serialport/stream');
SerialPort.Binding = require('@serialport/bindings');

/**
 * 스캔이 끝난 후, 선택된 포트로 시리얼포트를 오픈하는 클래스
 * 스캐너에서 open, initialize 가 일어나고,
 * 라우터에서 setRouter, connect 를 거쳐 통신한다.
 */
class Connector {
    static get DEFAULT_CONNECT_LOST_MILLS() {
        return 1000;
    }

    static get DEFAULT_SLAVE_DURATION() {
        return 1000;
    }

    constructor(hwModule, hardwareOptions) {
        this.options = hardwareOptions;
        this.hwModule = hwModule;

        /**
         * @type {MainRouter}
         */
        this.router = undefined;

        /**
         * @type {SerialPort}
         */
        this.serialPort = undefined;

        this.connected = false;
        this.received = false;
    }

    /**
     * MainRouter 를 세팅한다.
     * @param {MainRouter} router
     */
    setRouter(router) {
        this.router = router;
    }

    /**
     * 시리얼포트 생성자 옵션을 만든다.
     * @param serialPortOptions
     * @returns {Object} SerialPort 내 defaultSettings 참조
     * @private
     */
    _makeSerialPortOptions(serialPortOptions) {
        const _options = {
            autoOpen: true,
            baudRate: 9600,
            parity: 'none',
            dataBits: 8,
            stopBits: 1,
            bufferSize: 65536,
        };

        if (serialPortOptions.flowControl === 'hardware') {
            _options.rtscts = true;
        } else if (serialPortOptions.flowControl === 'software') {
            _options.xon = true;
            _options.xoff = true;
        }

        Object.assign(_options, serialPortOptions);
        return _options;
    }

    /**
     * 시리얼포트를 오픈한다.
     * @param {string} port COMPortName
     * @returns {Promise<SerialPort>}
     */
    open(port) {
        return new Promise((resolve, reject) => {
            const hardwareOptions = this.options;
            this.lostTimer = hardwareOptions.lostTimer || Connector.DEFAULT_CONNECT_LOST_MILLS;

            const serialPort = new SerialPort(port, this._makeSerialPortOptions(hardwareOptions));
            this.serialPort = serialPort;

            const { delimiter, byteDelimiter } = hardwareOptions;
            if (delimiter) {
                serialPort.parser = serialPort.pipe(new Readline({ delimiter }));
            } else if (byteDelimiter) {
                serialPort.parser = serialPort.pipe(new Delimiter({
                    delimiter: byteDelimiter,
                    includeDelimiter: true,
                }));
            }

            serialPort.on('error', reject);
            serialPort.on('open', (error) => {
                serialPort.removeAllListeners('open');
                if (error) {
                    reject(error);
                } else {
                    resolve(this.serialPort);
                }
            });
        });
    };

    /**
     * checkInitialData, requestInitialData 가 둘다 존재하는 경우 handShake 를 진행한다.
     * 둘 중 하나라도 없는 경우는 로직을 종료한다.
     * 만약 firmwareCheck 옵션이 활성화 된 경우면 executeFlash 를 세팅하고 종료한다.
     * 이 플래그는 라우터에서 flasher 를 바로 사용해야하는지 판단한다.
     *
     * @returns {Promise<void>} 준비완료 or 펌웨어체크 준비
     */
    initialize() {
        return new Promise((resolve, reject) => {
            const {
                control,
                duration = Connector.DEFAULT_SLAVE_DURATION,
                firmwarecheck,
            } = this.options;
            const hwModule = this.hwModule;
            const serialPortReadStream =
                        this.serialPort.parser ? this.serialPort.parser : this.serialPort;

            const runAsMaster = () => {
                serialPortReadStream.on('data', (data) => {
                    const result = hwModule.checkInitialData(data, this.options);

                    if (result === undefined) {
                        this.send(hwModule.requestInitialData());
                    } else {
                        this.serialPort.removeAllListeners('data');
                        serialPortReadStream.removeAllListeners('data');
                        clearTimeout(this.flashFirmware);
                        if (result === true) {
                            if (hwModule.setSerialPort) {
                                hwModule.setSerialPort(this.serialPort);
                            }
                            this.connected = true;
                            resolve();
                        } else {
                            reject(new Error('Invalid hardware'));
                        }
                    }
                });
            };

            const runAsSlave = () => {
                // 최소 한번은 requestInitialData 전송을 강제
                this.send(hwModule.requestInitialData(this.serialPort));
                this.slaveTimer = setInterval(() => {
                    this.send(hwModule.requestInitialData(this.serialPort));
                }, duration);

                // control type is slave
                serialPortReadStream.on('data', (data) => {
                    const result = hwModule.checkInitialData(data, this.options);
                    if (result !== undefined) {
                        this.serialPort.removeAllListeners('data');
                        serialPortReadStream.removeAllListeners('data');
                        clearTimeout(this.flashFirmware);
                        clearTimeout(this.slaveTimer);
                        if (result === true) {
                            if (hwModule.setSerialPort) {
                                hwModule.setSerialPort(this.serialPort);
                            }
                            if (hwModule.resetProperty) {
                                this.send(hwModule.resetProperty());
                            }
                            this.connected = true;
                            resolve();
                        } else {
                            reject(new Error('Invalid hardware'));
                        }
                    }
                });
            };

            if (firmwarecheck) {
                this.flashFirmware = setTimeout(() => {
                    if (this.serialPort) {
                        this.serialPort.parser ?
                            this.serialPort.parser.removeAllListeners('data') :
                            this.serialPort.removeAllListeners('data');
                        this.executeFlash = true;
                    }
                    resolve();
                }, 3000);
            }

            if (hwModule.checkInitialData && hwModule.requestInitialData) {
                if (control === 'master') {
                    runAsMaster();
                } else {
                    runAsSlave();
                }
            } else {
                resolve();
            }
        });
    }

    /**
     * router 와 hwModule 양쪽에 state 변경점을 보낸다.
     * @param {string} state
     * @private
     */
    _sendState(state) {
        this.hwModule.eventController && this.hwModule.eventController(state);
        this.router.sendState(state);
    }

    connect() {
        if (!this.router) {
            throw new Error('router must be set');
        }

        if (!this.serialPort) {
            throw new Error('serialPort must be open');
        }

        const router = this.router;
        const serialPort = this.serialPort;
        const hwModule = this.hwModule;
        const {
            control,
            duration = Connector.DEFAULT_SLAVE_DURATION,
            advertise,
            softwareReset,
        } = this.options;

        this.connected = false;
        this.received = true;

        if (hwModule.connect) {
            hwModule.connect();
        }
        this._sendState('connect');

        if (softwareReset) {
            serialPort.set({ dtr: false });
            setTimeout(() => {
                serialPort.set({ dtr: true });
            },1000);
        }

        if (hwModule.afterConnect) {
            hwModule.afterConnect(this, (state) => {
                this.router.sendState(state);
            });
        }

        const serialPortReadStream =
            serialPort.parser ? serialPort.pipe(serialPort.parser) : serialPort;

        serialPortReadStream.on('data', (data) => {
            if (!hwModule.validateLocalData || hwModule.validateLocalData(data)) {
                if (!this.connected) {
                    this.connected = true;
                    this._sendState('connected');
                }

                this.received = true;
                if (hwModule.handleLocalData) {
                    hwModule.handleLocalData(data);
                }

                // 서버로 데이터를 요청한다.
                router.setHandlerData();
                router.sendEncodedDataToServer();

                // 마스터모드인 경우, 데이터를 받자마자 디바이스로 데이터를 보낸다.
                if (control === 'master' && hwModule.requestLocalData) {
                    const data = hwModule.requestLocalData();
                    data && this.send(data);
                }
            }
        });

        serialPort.on('disconnect', () => {
            this.close();
            this._sendState('disconnected');
        });

        // 디바이스 연결 잃어버린 상태에 대한 관리를 모듈에 맡기거나, 직접 관리한다.
        if (hwModule.lostController) {
            hwModule.lostController(this, router.sendState.bind(router));
        } else {
            /*
             * this.lostTimer 타임 안에 데이터를 수신해야한다. 그렇지 않으면 연결해제처리한다.
             */
            this.connectionLostTimer = setInterval(() => {
                if (this.connected) {
                    if (this.received === false) {
                        this.connected = false;
                        this._sendState('lost');
                    }
                    this.received = false;
                }
            }, this.lostTimer);
        }

        if (duration && control !== 'master') {
            this.requestLocalDataInterval = setInterval(() => {
                if (hwModule.requestLocalData) {
                    const data = hwModule.requestLocalData();
                    data && this.send(data);
                }
                if (hwModule.getProperty) {
                    const data = hwModule.getProperty();
                    if (data) {
                        this.send(data);
                    }
                }
            }, duration);
        }

        if (advertise) {
            this.advertiseInterval = setInterval(() => {
                router.sendEncodedDataToServer();
            }, advertise);
        }
    }

    clear() {
        this.connected = false;
        if (this.connectionLostTimer) {
            clearInterval(this.connectionLostTimer);
            this.connectionLostTimer = undefined;
        }
        if (this.requestLocalDataInterval) {
            clearInterval(this.requestLocalDataInterval);
            this.requestLocalDataInterval = undefined;
        }
        if (this.advertiseInterval) {
            clearInterval(this.advertiseInterval);
            this.advertiseInterval = undefined;
        }
        if (this.serialPort) {
            this.serialPort.removeAllListeners();
            if (this.serialPort.parser) {
                this.serialPort.parser.removeAllListeners();
            }
        }
        if (this.flashFirmware) {
            clearTimeout(this.flashFirmware);
            this.flashFirmware = undefined;
        }
    };

    close() {
        this.clear();
        if (this.serialPort && this.serialPort.isOpen) {
            this.serialPort.close((e) => {
                this.serialPort = undefined;
            }, null);
        }
    };

    /**
     * 시리얼포트로 연결된 디바이스에 데이터를 보낸다.
     * @param data
     * @param callback
     */
    send(data, callback) {
        if (this.serialPort && this.serialPort.isOpen && data && !this.isSending) {
            this.isSending = true;

            if (this.options.stream === 'string') {
                data = Buffer.from(data, 'utf8');
            }
            console.log(data);
            this.serialPort.write(data, () => {
                if (this.serialPort) {
                    this.serialPort.drain(() => {
                        this.connected = true;
                        this.isSending = false;
                        callback && callback();
                    });
                }
            });
        }
    };
}

module.exports = Connector;
<commit_msg>주석 삭제<commit_after>'use strict';
const Readline = require('@serialport/parser-readline'); // modify
const Delimiter = require('@serialport/parser-delimiter');
const SerialPort = require('@serialport/stream');
SerialPort.Binding = require('@serialport/bindings');

/**
 * 스캔이 끝난 후, 선택된 포트로 시리얼포트를 오픈하는 클래스
 * 스캐너에서 open, initialize 가 일어나고,
 * 라우터에서 setRouter, connect 를 거쳐 통신한다.
 */
class Connector {
    static get DEFAULT_CONNECT_LOST_MILLS() {
        return 1000;
    }

    static get DEFAULT_SLAVE_DURATION() {
        return 1000;
    }

    constructor(hwModule, hardwareOptions) {
        this.options = hardwareOptions;
        this.hwModule = hwModule;

        /**
         * @type {MainRouter}
         */
        this.router = undefined;

        /**
         * @type {SerialPort}
         */
        this.serialPort = undefined;

        this.connected = false;
        this.received = false;
    }

    /**
     * MainRouter 를 세팅한다.
     * @param {MainRouter} router
     */
    setRouter(router) {
        this.router = router;
    }

    /**
     * 시리얼포트 생성자 옵션을 만든다.
     * @param serialPortOptions
     * @returns {Object} SerialPort 내 defaultSettings 참조
     * @private
     */
    _makeSerialPortOptions(serialPortOptions) {
        const _options = {
            autoOpen: true,
            baudRate: 9600,
            parity: 'none',
            dataBits: 8,
            stopBits: 1,
            bufferSize: 65536,
        };

        if (serialPortOptions.flowControl === 'hardware') {
            _options.rtscts = true;
        } else if (serialPortOptions.flowControl === 'software') {
            _options.xon = true;
            _options.xoff = true;
        }

        Object.assign(_options, serialPortOptions);
        return _options;
    }

    /**
     * 시리얼포트를 오픈한다.
     * @param {string} port COMPortName
     * @returns {Promise<SerialPort>}
     */
    open(port) {
        return new Promise((resolve, reject) => {
            const hardwareOptions = this.options;
            this.lostTimer = hardwareOptions.lostTimer || Connector.DEFAULT_CONNECT_LOST_MILLS;

            const serialPort = new SerialPort(port, this._makeSerialPortOptions(hardwareOptions));
            this.serialPort = serialPort;

            const { delimiter, byteDelimiter } = hardwareOptions;
            if (delimiter) {
                serialPort.parser = serialPort.pipe(new Readline({ delimiter }));
            } else if (byteDelimiter) {
                serialPort.parser = serialPort.pipe(new Delimiter({
                    delimiter: byteDelimiter,
                    includeDelimiter: true,
                }));
            }

            serialPort.on('error', reject);
            serialPort.on('open', (error) => {
                serialPort.removeAllListeners('open');
                if (error) {
                    reject(error);
                } else {
                    resolve(this.serialPort);
                }
            });
        });
    };

    /**
     * checkInitialData, requestInitialData 가 둘다 존재하는 경우 handShake 를 진행한다.
     * 둘 중 하나라도 없는 경우는 로직을 종료한다.
     * 만약 firmwareCheck 옵션이 활성화 된 경우면 executeFlash 를 세팅하고 종료한다.
     * 이 플래그는 라우터에서 flasher 를 바로 사용해야하는지 판단한다.
     *
     * @returns {Promise<void>} 준비완료 or 펌웨어체크 준비
     */
    initialize() {
        return new Promise((resolve, reject) => {
            const {
                control,
                duration = Connector.DEFAULT_SLAVE_DURATION,
                firmwarecheck,
            } = this.options;
            const hwModule = this.hwModule;
            const serialPortReadStream =
                        this.serialPort.parser ? this.serialPort.parser : this.serialPort;

            const runAsMaster = () => {
                serialPortReadStream.on('data', (data) => {
                    const result = hwModule.checkInitialData(data, this.options);

                    if (result === undefined) {
                        this.send(hwModule.requestInitialData());
                    } else {
                        this.serialPort.removeAllListeners('data');
                        serialPortReadStream.removeAllListeners('data');
                        clearTimeout(this.flashFirmware);
                        if (result === true) {
                            if (hwModule.setSerialPort) {
                                hwModule.setSerialPort(this.serialPort);
                            }
                            this.connected = true;
                            resolve();
                        } else {
                            reject(new Error('Invalid hardware'));
                        }
                    }
                });
            };

            const runAsSlave = () => {
                // 최소 한번은 requestInitialData 전송을 강제
                this.send(hwModule.requestInitialData(this.serialPort));
                this.slaveTimer = setInterval(() => {
                    this.send(hwModule.requestInitialData(this.serialPort));
                }, duration);

                // control type is slave
                serialPortReadStream.on('data', (data) => {
                    const result = hwModule.checkInitialData(data, this.options);
                    if (result !== undefined) {
                        this.serialPort.removeAllListeners('data');
                        serialPortReadStream.removeAllListeners('data');
                        clearTimeout(this.flashFirmware);
                        clearTimeout(this.slaveTimer);
                        if (result === true) {
                            if (hwModule.setSerialPort) {
                                hwModule.setSerialPort(this.serialPort);
                            }
                            if (hwModule.resetProperty) {
                                this.send(hwModule.resetProperty());
                            }
                            this.connected = true;
                            resolve();
                        } else {
                            reject(new Error('Invalid hardware'));
                        }
                    }
                });
            };

            if (firmwarecheck) {
                this.flashFirmware = setTimeout(() => {
                    if (this.serialPort) {
                        this.serialPort.parser ?
                            this.serialPort.parser.removeAllListeners('data') :
                            this.serialPort.removeAllListeners('data');
                        this.executeFlash = true;
                    }
                    resolve();
                }, 3000);
            }

            if (hwModule.checkInitialData && hwModule.requestInitialData) {
                if (control === 'master') {
                    runAsMaster();
                } else {
                    runAsSlave();
                }
            } else {
                resolve();
            }
        });
    }

    /**
     * router 와 hwModule 양쪽에 state 변경점을 보낸다.
     * @param {string} state
     * @private
     */
    _sendState(state) {
        this.hwModule.eventController && this.hwModule.eventController(state);
        this.router.sendState(state);
    }

    connect() {
        if (!this.router) {
            throw new Error('router must be set');
        }

        if (!this.serialPort) {
            throw new Error('serialPort must be open');
        }

        const router = this.router;
        const serialPort = this.serialPort;
        const hwModule = this.hwModule;
        const {
            control,
            duration = Connector.DEFAULT_SLAVE_DURATION,
            advertise,
            softwareReset,
        } = this.options;

        this.connected = false;
        this.received = true;

        if (hwModule.connect) {
            hwModule.connect();
        }
        this._sendState('connect');

        if (softwareReset) {
            serialPort.set({ dtr: false });
            setTimeout(() => {
                serialPort.set({ dtr: true });
            },1000);
        }

        if (hwModule.afterConnect) {
            hwModule.afterConnect(this, (state) => {
                this.router.sendState(state);
            });
        }

        const serialPortReadStream =
            serialPort.parser ? serialPort.pipe(serialPort.parser) : serialPort;

        serialPortReadStream.on('data', (data) => {
            if (!hwModule.validateLocalData || hwModule.validateLocalData(data)) {
                if (!this.connected) {
                    this.connected = true;
                    this._sendState('connected');
                }

                this.received = true;
                if (hwModule.handleLocalData) {
                    hwModule.handleLocalData(data);
                }

                // 서버로 데이터를 요청한다.
                router.setHandlerData();
                router.sendEncodedDataToServer();

                // 마스터모드인 경우, 데이터를 받자마자 디바이스로 데이터를 보낸다.
                if (control === 'master' && hwModule.requestLocalData) {
                    const data = hwModule.requestLocalData();
                    data && this.send(data);
                }
            }
        });

        serialPort.on('disconnect', () => {
            this.close();
            this._sendState('disconnected');
        });

        // 디바이스 연결 잃어버린 상태에 대한 관리를 모듈에 맡기거나, 직접 관리한다.
        if (hwModule.lostController) {
            hwModule.lostController(this, router.sendState.bind(router));
        } else {
            /*
             * this.lostTimer 타임 안에 데이터를 수신해야한다. 그렇지 않으면 연결해제처리한다.
             */
            this.connectionLostTimer = setInterval(() => {
                if (this.connected) {
                    if (this.received === false) {
                        this.connected = false;
                        this._sendState('lost');
                    }
                    this.received = false;
                }
            }, this.lostTimer);
        }

        if (duration && control !== 'master') {
            this.requestLocalDataInterval = setInterval(() => {
                if (hwModule.requestLocalData) {
                    const data = hwModule.requestLocalData();
                    data && this.send(data);
                }
                if (hwModule.getProperty) {
                    const data = hwModule.getProperty();
                    if (data) {
                        this.send(data);
                    }
                }
            }, duration);
        }

        if (advertise) {
            this.advertiseInterval = setInterval(() => {
                router.sendEncodedDataToServer();
            }, advertise);
        }
    }

    clear() {
        this.connected = false;
        if (this.connectionLostTimer) {
            clearInterval(this.connectionLostTimer);
            this.connectionLostTimer = undefined;
        }
        if (this.requestLocalDataInterval) {
            clearInterval(this.requestLocalDataInterval);
            this.requestLocalDataInterval = undefined;
        }
        if (this.advertiseInterval) {
            clearInterval(this.advertiseInterval);
            this.advertiseInterval = undefined;
        }
        if (this.serialPort) {
            this.serialPort.removeAllListeners();
            if (this.serialPort.parser) {
                this.serialPort.parser.removeAllListeners();
            }
        }
        if (this.flashFirmware) {
            clearTimeout(this.flashFirmware);
            this.flashFirmware = undefined;
        }
    };

    close() {
        this.clear();
        if (this.serialPort && this.serialPort.isOpen) {
            this.serialPort.close((e) => {
                this.serialPort = undefined;
            }, null);
        }
    };

    /**
     * 시리얼포트로 연결된 디바이스에 데이터를 보낸다.
     * @param data
     * @param callback
     */
    send(data, callback) {
        if (this.serialPort && this.serialPort.isOpen && data && !this.isSending) {
            this.isSending = true;

            if (this.options.stream === 'string') {
                data = Buffer.from(data, 'utf8');
            }
            this.serialPort.write(data, () => {
                if (this.serialPort) {
                    this.serialPort.drain(() => {
                        this.connected = true;
                        this.isSending = false;
                        callback && callback();
                    });
                }
            });
        }
    };
}

module.exports = Connector;
<|endoftext|>


<commit_before>function log(msg, opt_color) {
  var msgNode = document.createElement('div');
  if (opt_color) {
	msgNode.style.color = opt_color;
  }
  msgNode.innerText = msg;
  document.getElementById('log').appendChild(msgNode);
}

function assertEquals(expected, actual, opt_msg) {
  if (expected == actual) {
	log('PASS: ' + expected + ' (as expected)');
  } else {
	var msg = opt_msg ? ' ' + opt_msg : '';
	log('FAIL: ' + expected + ' (expected) != ' + actual + ' (actual)' + msg, 'red');
  }
}

var TEST_DATA = {
  'http://example.com/post': 'http://example.com/post',
  'http://example.com/post?foo=bar': 'http://example.com/post?foo=bar',
  'http://example.com/post?utm_source=src&utm_medium=medium&utm_campaign=campaign&utm_reader=feedly': 'http://example.com/post',
  'http://example.com/post?mc_cid=1234&mc_eid=4321': 'http://example.com/post',
  'http://example.com/post?foo=bar&utm_source=src': 'http://example.com/post?foo=bar',
  'http://example.com/post?utm_source=src&foo=bar': 'http://example.com/post?foo=bar',
  'http://example.com/post?utm_source=src#foo=bar': 'http://example.com/post#foo=bar',

  'https://www.youtube.com/watch?v=YlGqN3AKOsA&feature=kp': 'https://www.youtube.com/watch?v=YlGqN3AKOsA',
  'https://www.youtube.com/watch?feature=youtu.be&v=YlGqN3AKOsA': 'https://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&feature=kp': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&app=desktop': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&feature=kp&app=desktop': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?app=desktop&v=YlGqN3AKOsA': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&ac=': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&ac=test': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?ac=&v=YlGqN3AKOsA': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&ac=&app=desktop': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'https://www.youtube.com/watch?v=3OHBlPvK9Ek&src_vid=4KHCkXN2F8I&annotation_id=annotation_1193924099': 'https://www.youtube.com/watch?v=3OHBlPvK9Ek',
}

function runTests() {
  for (var input in TEST_DATA) {
	assertEquals(TEST_DATA[input], getStrippedUrl(input));
  }
}

window.addEventListener('load', runTests, false);<commit_msg>Add tests for Yandex openstat parameters.<commit_after>function log(msg, opt_color) {
  var msgNode = document.createElement('div');
  if (opt_color) {
	msgNode.style.color = opt_color;
  }
  msgNode.innerText = msg;
  document.getElementById('log').appendChild(msgNode);
}

function assertEquals(expected, actual, opt_msg) {
  if (expected == actual) {
	log('PASS: ' + expected + ' (as expected)');
  } else {
	var msg = opt_msg ? ' ' + opt_msg : '';
	log('FAIL: ' + expected + ' (expected) != ' + actual + ' (actual)' + msg, 'red');
  }
}

var TEST_DATA = {
  'http://example.com/post': 'http://example.com/post',
  'http://example.com/post?foo=bar': 'http://example.com/post?foo=bar',
  'http://example.com/post?utm_source=src&utm_medium=medium&utm_campaign=campaign&utm_reader=feedly': 'http://example.com/post',
  'http://example.com/post?mc_cid=1234&mc_eid=4321': 'http://example.com/post',
  'http://example.com/post?foo=bar&utm_source=src': 'http://example.com/post?foo=bar',
  'http://example.com/post?utm_source=src&foo=bar': 'http://example.com/post?foo=bar',
  'http://example.com/post?utm_source=src#foo=bar': 'http://example.com/post#foo=bar',

  'https://www.youtube.com/watch?v=YlGqN3AKOsA&feature=kp': 'https://www.youtube.com/watch?v=YlGqN3AKOsA',
  'https://www.youtube.com/watch?feature=youtu.be&v=YlGqN3AKOsA': 'https://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&feature=kp': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&app=desktop': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&feature=kp&app=desktop': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?app=desktop&v=YlGqN3AKOsA': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&ac=': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&ac=test': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?ac=&v=YlGqN3AKOsA': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'http://www.youtube.com/watch?v=YlGqN3AKOsA&ac=&app=desktop': 'http://www.youtube.com/watch?v=YlGqN3AKOsA',
  'https://www.youtube.com/watch?v=3OHBlPvK9Ek&src_vid=4KHCkXN2F8I&annotation_id=annotation_1193924099': 'https://www.youtube.com/watch?v=3OHBlPvK9Ek',

  'http://www.site.ru/?_openstat=ZGlyZWN0LnlhbmRleC5ydTsxMjM0OzU2Nzg5O3lhbmRleC5ydTpwcmVtaXVt': 'http://www.site.ru/',
  'http://www.site.ru/path?_openstat=ZGlyZWN0LnlhbmRleC5ydTsxMjM0OzU2Nzg5O3lhbmRleC5ydTpwcmVtaXVt': 'http://www.site.ru/path',
  'http://www.site.ru/path?foo=bar&_openstat=ZGlyZWN0LnlhbmRleC5ydTsxMjM0OzU2Nzg5O3lhbmRleC5ydTpwcmVtaXVt': 'http://www.site.ru/path?foo=bar',
  'http://www.site.ru/path?_openstat=ZGlyZWN0LnlhbmRleC5ydTsxMjM0OzU2Nzg5O3lhbmRleC5ydTpwcmVtaXVt&foo=bar': 'http://www.site.ru/path?foo=bar',
  'http://www.site.ru/path?_openstat=ZGlyZWN0LnlhbmRleC5ydTsxMjM0OzU2Nzg5O3lhbmRleC5ydTpwcmVtaXVt#fragment': 'http://www.site.ru/path#fragment',
}

function runTests() {
  for (var input in TEST_DATA) {
	assertEquals(TEST_DATA[input], getStrippedUrl(input));
  }
}

window.addEventListener('load', runTests, false);
<|endoftext|>


<commit_before>/**
 * @fileoverview About this file.
 * User: mbikt
 * Date: 4/24/12
 * @externs
 */

/**
* Socket IO
* @constructor
*/
function Socket() {}

/**
* @param {string} channel
* @param {Function} listener
*/
Socket.prototype.on = function(channel, listener) {};

/**
* @param {string} channel
* @param {Object} obj
*/
Socket.prototype.emit = function(channel, obj) {};

/**
* Socket IO service
* @constructor
*/
function io() {}

/**
* @param {string} server
* @return {Socket}
*/
io.prototype.connect = function(server) {};

//
///**
// * New IndexedDB interface not in closure externs.
// * This must be remove when they updated.
// * @constructor
// */
//
///**
// * @extends {IDBRequest}
// * @constructor
// */
//var IDBOpenDBRequest = function() {};
//
///**
// *
// * @param ev
// */
//IDBOpenDBRequest.prototype.onblocked = function(ev) {};
//
///**
// *
// * @param ev
// */
//IDBOpenDBRequest.prototype.onupgradeneeded = function(ev) {};

/**
 * @final
 * @type {boolean}
 */
IDBIndex.prototype.multiEntry;

/**
 * @final
 * @type {boolean}
 */
IDBObjectStore.prototype.autoIncrement;
//
//
///**
// * Closure compiler incorrectly define as Array.<string>
//* @final
//* @type {DOMStringList}
//*/
//IDBDatabase.prototype.objectStoreNames;
//
//
///**
// * @constructor
// */
//var IDBVersionChangeEvent = function() {};
//
///**
// * @final
// * @type {string}
// */
//IDBVersionChangeEvent.prototype.version;

/**
 * @extends {IDBCursor}
 * @constructor
 */
var IDBCursorWithValue = function() {};

/**
 * @type {*}
 */
IDBCursorWithValue.prototype.value;

/**
 * @type {*}
 */
IDBCursorWithValue.prototype.primaryKey;

//
///**
//* Closure compiler incorrectly define as Array.<string>
//* @final
//* @type {DOMStringList}
//*/
//IDBObjectStore.prototype.indexNames;

///**
// * @param {*=} key Key identifying the record to be retrieved.
// * @return {!IDBRequest} The IDBRequest object.
// */
//IDBObjectStore.prototype.count = function(key) {};

/**
 * @param {*=} key Key identifying the record to be retrieved.
 * @return {!IDBRequest} The IDBRequest object.
 */
IDBIndex.prototype.count = function(key) {};

/**
 *
 * @param {*} first
 * @param {*} second
 * @return {number}
 */
IDBFactory.prototype.cmp = function(first, second) {};

/**
 * @type {!DOMError}
 * @const
 */
IDBRequest.prototype.error;

<commit_msg>compiler update<commit_after>/**
 * @fileoverview About this file.
 * User: mbikt
 * Date: 4/24/12
 * @externs
 */

/**
* Socket IO
* @constructor
*/
function Socket() {}

/**
* @param {string} channel
* @param {Function} listener
*/
Socket.prototype.on = function(channel, listener) {};

/**
* @param {string} channel
* @param {Object} obj
*/
Socket.prototype.emit = function(channel, obj) {};

/**
* Socket IO service
* @constructor
*/
function io() {}

/**
* @param {string} server
* @return {Socket}
*/
io.prototype.connect = function(server) {};

//
///**
// * New IndexedDB interface not in closure externs.
// * This must be remove when they updated.
// * @constructor
// */
//
///**
// * @extends {IDBRequest}
// * @constructor
// */
//var IDBOpenDBRequest = function() {};
//
///**
// *
// * @param ev
// */
//IDBOpenDBRequest.prototype.onblocked = function(ev) {};
//
///**
// *
// * @param ev
// */
//IDBOpenDBRequest.prototype.onupgradeneeded = function(ev) {};

/**
 * @final
 * @type {boolean}
 */
IDBIndex.prototype.multiEntry;

/**
 * @final
 * @type {boolean}
 */
IDBObjectStore.prototype.autoIncrement;
//
//
///**
// * Closure compiler incorrectly define as Array.<string>
//* @final
//* @type {DOMStringList}
//*/
//IDBDatabase.prototype.objectStoreNames;
//
//
///**
// * @constructor
// */
//var IDBVersionChangeEvent = function() {};
//
///**
// * @final
// * @type {string}
// */
//IDBVersionChangeEvent.prototype.version;

/**
 * @param {*=} key Key identifying the record to be retrieved.
 * @return {!IDBRequest} The IDBRequest object.
 */
IDBIndex.prototype.count = function(key) {};

/**
 *
 * @param {*} first
 * @param {*} second
 * @return {number}
 */
IDBFactory.prototype.cmp = function(first, second) {};

/**
 * @type {!DOMError}
 * @const
 */
IDBRequest.prototype.error;

<|endoftext|>


<commit_before>
foodService.$inject = ['$http', 'apiUrl'];

export default function foodService($http, apiUrl) {
    return {
        getAll() {
            return $http.get(`${apiUrl}/foods`)
                .then(res => res.data);
        },
        add(food) {
            return $http.post(`${apiUrl}/foods`, food)
                .then(res => res.data);
        }
    };
};
<commit_msg>Fixed food service<commit_after>
foodService.$inject = ['$http', 'apiUrl'];

export default function foodService($http, apiUrl) {
    return {
        get() {
            return $http.get(`${apiUrl}/foods`)
                .then(res => res.data);
        },
        add(food) {
            return $http.post(`${apiUrl}/foods`, food)
                .then(res => res.data);
        }
    };
};
<|endoftext|>


<commit_before>for( i = 1;i<document.getElementsByClassName("textInput mentionsTextarea uiTextareaAutogrow uiTextareaNoResize UFIAddCommentInput DOMControl_placeholder").length;i++) {
    document.getElementsByClassName("textInput mentionsTextarea uiTextareaAutogrow uiTextareaNoResize UFIAddCommentInput DOMControl_placeholder")[i].click();
    var input = $( "textInput mentionsTextarea uiTextareaAutogrow uiTextareaNoResize UFIAddCommentInput DOMControl_placeholder" );
    input.val( input.val() + "testing" );
}
void(0);

for( i = 1;i<document.getElementsByClassName("UFIAddComment").length;i++) {
    document.getElementsByClassName("UFIAddComment")[i].click();
    var input = $( "UFIAddComment" );
    input.val( input.val() + "testing" );
}
void(0);
<commit_msg>Delete edits<commit_after>for( i = 1;i<document.getElementsByClassName("textInput mentionsTextarea uiTextareaAutogrow uiTextareaNoResize UFIAddCommentInput DOMControl_placeholder").length;i++) {
    document.getElementsByClassName("textInput mentionsTextarea uiTextareaAutogrow uiTextareaNoResize UFIAddCommentInput DOMControl_placeholder")[i].click();
    var input = $( "textInput mentionsTextarea uiTextareaAutogrow uiTextareaNoResize UFIAddCommentInput DOMControl_placeholder" );
    input.val( input.val() + "testing" );
}
void(0);

for( i = 1;i<document.getElementsByClassName("UFIAddComment").length;i++) {
    document.getElementsByClassName("UFIAddComment")[i].click();
    var input = $( "UFIAddComment" );
    input.val( input.val() + "testing" );
}
void(0);<|endoftext|>


<commit_before>/* eslint-disable no-console */

const path = require('path');
const fs = require('fs');
const http = require('http');
const https = require('https');

const MAX_REDIRECTS = 3;
const MAX_RESPONSE_CHUNKS = 1000;
const KNOWN_ICONS = {
    'gmail.com': 'https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico'
};
const DEBUG = process.env.DEBUG_FAVICON;
const IP_THROTTLING_MS = process.env.IP_THROTTLING_MS || 1000;
const IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD =
    process.env.IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD || 100;
const IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS =
    process.env.IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS || 60 * 60 * 1000;
const lastRequestDatePerIp = new Map();

const bannedReferrers = {};

fs.readFileSync(path.resolve(__dirname, 'conf/banned-referrers.txt'), 'utf8')
    .split('\n')
    .map((line) => line.trim())
    .filter((line) => line && !line.startsWith('#'))
    .forEach((line) => {
        bannedReferrers[line] = true;
    });

function faviconApp(req, res) {
    if (req.url === '/favicon.ico') {
        res.writeHead(204);
        res.end();
        return;
    }
    if (req.url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end(
            'This is a service for loading website favicons with CORS\n\n' +
                'Usage: GET /domain.com\n' +
                'Questions, source code: https://github.com/keeweb/favicon-proxy'
        );
        return;
    }

    let blockStatusCode = 0;
    let blockReason = '';
    if (req.headers.referer) {
        let refererDomain = req.headers.referer.match(/^\w+:\/\/([^/?]+)/);
        if (refererDomain) {
            refererDomain = refererDomain[1].toLowerCase();
        }
        if (bannedReferrers[refererDomain]) {
            blockReason = 'Forbidden';
            blockStatusCode = 403;
        }
    }

    const clientIp = req.headers['cf-connecting-ip'] || req.connection.remoteAddress;
    const now = new Date();

    if (needThrottle(clientIp, now)) {
        blockReason = 'Too many requests';
        blockStatusCode = 429;
    }

    console.log(
        now.toISOString(),
        'GET',
        req.url,
        req.headers.origin || '-',
        req.headers.referer || '-',
        req.headers['user-agent'] || '-',
        clientIp,
        req.headers['cf-ipcountry'] || '-',
        blockReason || '-'
    );
    if (blockReason) {
        return returnError(blockStatusCode || 403, res, blockReason);
    }
    const domain = req.url.substr(1).toLowerCase();
    if (domain.indexOf('.') < 0 || domain.match(/[\/:?]|(\.\.)/)) {
        return returnError(404, res, 'Usage: GET /domain.com');
    }
    if (domain.indexOf('keeweb.info') >= 0) {
        return returnError(403, res, 'No, I cannot get my own favicon');
    }
    const faviconUrl = KNOWN_ICONS[domain] || 'http://' + domain + '/favicon.ico';
    loadResource(faviconUrl)
        .then((srvRes) => {
            const contentType = srvRes.headers['content-type'];
            if (contentType.startsWith('image/') || contentType === 'application/octet-stream') {
                return pipeResponse(res, srvRes);
            } else {
                throw 'Bad content-type';
            }
        })
        .catch((e) => {
            if (e === 'Status 404' || e === 'Bad content-type') {
                loadResource('http://' + domain)
                    .then((srvRes) => {
                        readHtml(srvRes)
                            .then((html) => {
                                const iconUrl = getIconUrl(html, domain);
                                if (iconUrl) {
                                    loadResource(iconUrl)
                                        .then((srvRes) => {
                                            pipeResponse(res, srvRes);
                                        })
                                        .catch((e) => returnError(500, res, e));
                                } else {
                                    returnError(404, res, 'No favicon');
                                }
                            })
                            .catch((e) => returnError(500, res, e));
                    })
                    .catch((e) => returnError(500, res, e));
            } else {
                returnError(500, res, e);
            }
        });
}

function loadResource(url, redirectNum) {
    DEBUG && console.log('GET', url);
    return new Promise((resolve, reject) => {
        const proto = url.startsWith('https://')
            ? https
            : url.startsWith('http://')
            ? http
            : undefined;
        if (!proto) {
            return reject('Invalid protocol');
        }
        if (/:\/\/(127\.|192\.|0\.0\.|localhost|(\w+\.)?keeweb\.info)/i.test(url)) {
            return reject('Bad redirect: ' + url);
        }
        const serverReq = proto.get(url, (srvRes) => {
            DEBUG && console.log(srvRes.statusCode);
            if (srvRes.statusCode > 300 && srvRes.statusCode < 400 && srvRes.headers.location) {
                if (redirectNum > MAX_REDIRECTS) {
                    reject('Too many redirects');
                } else {
                    resolve(loadResource(srvRes.headers.location, (redirectNum || 0) + 1));
                }
            } else if (srvRes.statusCode === 200) {
                resolve(srvRes);
            } else {
                reject('Status ' + srvRes.statusCode);
            }
        });
        serverReq.on('error', (e) => {
            reject(e.message);
        });
        serverReq.end();
    });
}

function readHtml(stream) {
    return new Promise((resolve, reject) => {
        const chunks = [];
        stream.on('data', (chunk) => {
            if (chunks.length > MAX_RESPONSE_CHUNKS) {
                return reject('Response too large');
            } else {
                chunks.push(chunk);
            }
        });
        stream.on('error', () => {
            reject('HTML read error');
        });
        stream.on('end', () => {
            resolve(Buffer.concat(chunks).toString('utf8'));
        });
    });
}

function getIconUrl(html, domain) {
    const MAX_SIZE = 96;
    let match;
    const re = /<link\s+[^>]*rel=["']?(?:shortcut )?icon["']?[^>]*>/g;
    let iconHref,
        iconSize = 0;
    do {
        match = re.exec(html);
        if (match) {
            let href = /href=(["'])([^'"]+)"*\1/.exec(match[0]);
            if (href) {
                href = href[2];
            }
            const sizes = /sizes=["']?(\d+)/.exec(match[0]);
            if (sizes) {
                const size = +sizes[1];
                if (size && size > iconSize && size <= MAX_SIZE) {
                    iconHref = href;
                    iconSize = size;
                }
            } else if (!iconHref) {
                iconHref = href;
            }
        }
    } while (match);
    if (/\.(png|jpg|svg|gif|ico)/.test(iconHref)) {
        if (iconHref.indexOf('://') > 0) {
            return iconHref;
        } else {
            if (!iconHref.startsWith('/')) {
                iconHref = '/' + iconHref;
            }
            if (iconHref.startsWith('//')) {
                return 'http:' + iconHref;
            }
            return 'http://' + domain + iconHref;
        }
    }
}

function pipeResponse(res, srvRes) {
    res.writeHead(200, {
        'Content-Type': 'image/x-icon',
        'Access-Control-Allow-Origin': '*'
    });
    srvRes.pipe(res, { end: true });
}

function needThrottle(clientIp, now) {
    if (!IP_THROTTLING_MS) {
        return false;
    }

    let lastRequestDate = lastRequestDatePerIp.get(clientIp);
    let throttled = false;

    let newLastRequestDate = now.getTime();
    if (lastRequestDate) {
        const dateDiff = now - lastRequestDate;
        if (dateDiff < IP_THROTTLING_MS) {
            if (
                IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD &&
                IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS &&
                dateDiff < IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD
            ) {
                newLastRequestDate += IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS;
            }
            throttled = true;
        }
    }

    lastRequestDatePerIp.set(clientIp, newLastRequestDate);

    if (lastRequestDatePerIp.size > 50) {
        for (const [ip, dt] of lastRequestDatePerIp.entries()) {
            if (now - dt > IP_THROTTLING_MS) {
                lastRequestDatePerIp.delete(ip);
            }
        }
    }

    return throttled;
}

function returnError(code, res, err) {
    res.writeHead(code, { 'Content-Type': 'text/plain' });
    return res.end(String(err));
}

module.exports = faviconApp;
<commit_msg>int conversion<commit_after>/* eslint-disable no-console */

const path = require('path');
const fs = require('fs');
const http = require('http');
const https = require('https');

const MAX_REDIRECTS = 3;
const MAX_RESPONSE_CHUNKS = 1000;
const KNOWN_ICONS = {
    'gmail.com': 'https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico'
};
const DEBUG = process.env.DEBUG_FAVICON;
const IP_THROTTLING_MS = +(process.env.IP_THROTTLING_MS || 1000);
const IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD = +(
    process.env.IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD || 100
);
const IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS = +(
    process.env.IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS || 60 * 60 * 1000
);
const lastRequestDatePerIp = new Map();

const bannedReferrers = {};

fs.readFileSync(path.resolve(__dirname, 'conf/banned-referrers.txt'), 'utf8')
    .split('\n')
    .map((line) => line.trim())
    .filter((line) => line && !line.startsWith('#'))
    .forEach((line) => {
        bannedReferrers[line] = true;
    });

function faviconApp(req, res) {
    if (req.url === '/favicon.ico') {
        res.writeHead(204);
        res.end();
        return;
    }
    if (req.url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end(
            'This is a service for loading website favicons with CORS\n\n' +
                'Usage: GET /domain.com\n' +
                'Questions, source code: https://github.com/keeweb/favicon-proxy'
        );
        return;
    }

    let blockStatusCode = 0;
    let blockReason = '';
    if (req.headers.referer) {
        let refererDomain = req.headers.referer.match(/^\w+:\/\/([^/?]+)/);
        if (refererDomain) {
            refererDomain = refererDomain[1].toLowerCase();
        }
        if (bannedReferrers[refererDomain]) {
            blockReason = 'Forbidden';
            blockStatusCode = 403;
        }
    }

    const clientIp = req.headers['cf-connecting-ip'] || req.connection.remoteAddress;
    const now = new Date();

    if (needThrottle(clientIp, now)) {
        blockReason = 'Too many requests';
        blockStatusCode = 429;
    }

    console.log(
        now.toISOString(),
        'GET',
        req.url,
        req.headers.origin || '-',
        req.headers.referer || '-',
        req.headers['user-agent'] || '-',
        clientIp,
        req.headers['cf-ipcountry'] || '-',
        blockReason || '-'
    );
    if (blockReason) {
        return returnError(blockStatusCode || 403, res, blockReason);
    }
    const domain = req.url.substr(1).toLowerCase();
    if (domain.indexOf('.') < 0 || domain.match(/[\/:?]|(\.\.)/)) {
        return returnError(404, res, 'Usage: GET /domain.com');
    }
    if (domain.indexOf('keeweb.info') >= 0) {
        return returnError(403, res, 'No, I cannot get my own favicon');
    }
    const faviconUrl = KNOWN_ICONS[domain] || 'http://' + domain + '/favicon.ico';
    loadResource(faviconUrl)
        .then((srvRes) => {
            const contentType = srvRes.headers['content-type'];
            if (contentType.startsWith('image/') || contentType === 'application/octet-stream') {
                return pipeResponse(res, srvRes);
            } else {
                throw 'Bad content-type';
            }
        })
        .catch((e) => {
            if (e === 'Status 404' || e === 'Bad content-type') {
                loadResource('http://' + domain)
                    .then((srvRes) => {
                        readHtml(srvRes)
                            .then((html) => {
                                const iconUrl = getIconUrl(html, domain);
                                if (iconUrl) {
                                    loadResource(iconUrl)
                                        .then((srvRes) => {
                                            pipeResponse(res, srvRes);
                                        })
                                        .catch((e) => returnError(500, res, e));
                                } else {
                                    returnError(404, res, 'No favicon');
                                }
                            })
                            .catch((e) => returnError(500, res, e));
                    })
                    .catch((e) => returnError(500, res, e));
            } else {
                returnError(500, res, e);
            }
        });
}

function loadResource(url, redirectNum) {
    DEBUG && console.log('GET', url);
    return new Promise((resolve, reject) => {
        const proto = url.startsWith('https://')
            ? https
            : url.startsWith('http://')
            ? http
            : undefined;
        if (!proto) {
            return reject('Invalid protocol');
        }
        if (/:\/\/(127\.|192\.|0\.0\.|localhost|(\w+\.)?keeweb\.info)/i.test(url)) {
            return reject('Bad redirect: ' + url);
        }
        const serverReq = proto.get(url, (srvRes) => {
            DEBUG && console.log(srvRes.statusCode);
            if (srvRes.statusCode > 300 && srvRes.statusCode < 400 && srvRes.headers.location) {
                if (redirectNum > MAX_REDIRECTS) {
                    reject('Too many redirects');
                } else {
                    resolve(loadResource(srvRes.headers.location, (redirectNum || 0) + 1));
                }
            } else if (srvRes.statusCode === 200) {
                resolve(srvRes);
            } else {
                reject('Status ' + srvRes.statusCode);
            }
        });
        serverReq.on('error', (e) => {
            reject(e.message);
        });
        serverReq.end();
    });
}

function readHtml(stream) {
    return new Promise((resolve, reject) => {
        const chunks = [];
        stream.on('data', (chunk) => {
            if (chunks.length > MAX_RESPONSE_CHUNKS) {
                return reject('Response too large');
            } else {
                chunks.push(chunk);
            }
        });
        stream.on('error', () => {
            reject('HTML read error');
        });
        stream.on('end', () => {
            resolve(Buffer.concat(chunks).toString('utf8'));
        });
    });
}

function getIconUrl(html, domain) {
    const MAX_SIZE = 96;
    let match;
    const re = /<link\s+[^>]*rel=["']?(?:shortcut )?icon["']?[^>]*>/g;
    let iconHref,
        iconSize = 0;
    do {
        match = re.exec(html);
        if (match) {
            let href = /href=(["'])([^'"]+)"*\1/.exec(match[0]);
            if (href) {
                href = href[2];
            }
            const sizes = /sizes=["']?(\d+)/.exec(match[0]);
            if (sizes) {
                const size = +sizes[1];
                if (size && size > iconSize && size <= MAX_SIZE) {
                    iconHref = href;
                    iconSize = size;
                }
            } else if (!iconHref) {
                iconHref = href;
            }
        }
    } while (match);
    if (/\.(png|jpg|svg|gif|ico)/.test(iconHref)) {
        if (iconHref.indexOf('://') > 0) {
            return iconHref;
        } else {
            if (!iconHref.startsWith('/')) {
                iconHref = '/' + iconHref;
            }
            if (iconHref.startsWith('//')) {
                return 'http:' + iconHref;
            }
            return 'http://' + domain + iconHref;
        }
    }
}

function pipeResponse(res, srvRes) {
    res.writeHead(200, {
        'Content-Type': 'image/x-icon',
        'Access-Control-Allow-Origin': '*'
    });
    srvRes.pipe(res, { end: true });
}

function needThrottle(clientIp, now) {
    if (!IP_THROTTLING_MS) {
        return false;
    }

    let lastRequestDate = lastRequestDatePerIp.get(clientIp);
    let throttled = false;

    let newLastRequestDate = now.getTime();
    if (lastRequestDate) {
        const dateDiff = now - lastRequestDate;
        if (dateDiff < IP_THROTTLING_MS) {
            if (
                IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD &&
                IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS &&
                dateDiff < IP_THROTTLING_AGGRESSIVE_LOCKDOWN_DETECTION_THRESHOLD
            ) {
                newLastRequestDate += IP_THROTTLING_AGGRESSIVE_LOCKDOWN_TIME_MS;
            }
            throttled = true;
        }
    }

    lastRequestDatePerIp.set(clientIp, newLastRequestDate);

    if (lastRequestDatePerIp.size > 50) {
        for (const [ip, dt] of lastRequestDatePerIp.entries()) {
            if (now - dt > IP_THROTTLING_MS) {
                lastRequestDatePerIp.delete(ip);
            }
        }
    }

    return throttled;
}

function returnError(code, res, err) {
    res.writeHead(code, { 'Content-Type': 'text/plain' });
    return res.end(String(err));
}

module.exports = faviconApp;
<|endoftext|>


<commit_before>ZiggeoSdk = require("../index.js");

var app_token = process.argv[2];
var private_key = process.argv[3];
var filename = process.argv[4];
var ops_time = process.argv[5];

var videos = [];

ZiggeoSdk.init(app_token, private_key);
var upload_time = Math.floor(Date.now() / 1000);
var delete_time = 0;
uploadVideo();
var download_counter = 0;
var delete_counter = 0;
function uploadVideo(){
	if(download_counter >= ops_time){
		upload_time = Math.floor(Date.now() / 1000) - upload_time;
		upload_time = upload_time/ops_time;
		console.log("Upload: "+upload_time);
		delete_time = Math.floor(Date.now() / 1000);
		deleteVideo();
		return;
	}
	ZiggeoSdk.Videos.create({
		file: filename
	}, function(data){
		console.log(data.token);
		videos.push(data.token);
		download_counter += 1;
		uploadVideo();
	});
}

function deleteVideo(){
	if(delete_counter >= ops_time){
		delete_time = Math.floor(Date.now() / 1000) - delete_time;
		delete_time = delete_time/ops_time;
		console.log("Delete: "+delete_time);
	}
	ZiggeoSdk.Videos.destroy(videos[delete_counter], function(){
		delete_counter += 1;
		deleteVideo();
	});
}<commit_msg>benchmark script, download part<commit_after>ZiggeoSdk = require("../index.js");

var app_token = process.argv[2];
var private_key = process.argv[3];
var filename = process.argv[4];
var ops_time = process.argv[5];

var videos = [];

ZiggeoSdk.init(app_token, private_key);
var upload_time = Math.floor(Date.now() / 1000);
var download_time = 0;
var delete_time = 0;
uploadVideo();
var upload_counter = 0;
var download_counter = 0;
var delete_counter = 0;
function uploadVideo(){
	if(upload_counter >= ops_time){
		upload_time = Math.floor(Date.now() / 1000) - upload_time;
		upload_time = upload_time/ops_time;
		console.log("Upload: "+upload_time);
		download_time = Math.floor(Date.now() / 1000);
		downloadVideo();
		return;
	}
	ZiggeoSdk.Videos.create({
		file: filename
	}, function(data){
		console.log(data.token);
		videos.push(data.token);
		upload_counter += 1;
		uploadVideo();
	});
}

function downloadVideo(){
	if(download_counter >= ops_time){
		download_time = Math.floor(Date.now() / 1000) - download_time;
		download_time = download_time/ops_time;
		console.log("Download: "+download_time);
		delete_time = Math.floor(Date.now() / 1000);
		deleteVideo();
		return;
	}
	ZiggeoSdk.Videos.download_video(videos[download_counter], function(){
		download_counter += 1;
		downloadVideo();
	});
}

function deleteVideo(){
	if(delete_counter >= ops_time){
		delete_time = Math.floor(Date.now() / 1000) - delete_time;
		delete_time = delete_time/ops_time;
		console.log("Delete: "+delete_time);
		return;
	}
	ZiggeoSdk.Videos.destroy(videos[delete_counter], function(){
		delete_counter += 1;
		deleteVideo();
	});
}
<|endoftext|>


<commit_before>/* globals window, document */
( function() {

// Find the script element
var scripts = document.getElementsByTagName( "script" );
var script = scripts[ scripts.length - 1 ];

// Read the modules
var modules = script.getAttribute( "data-modules" );
var composite = script.getAttribute( "data-composite" ) || false;
var pathParts = window.location.pathname.split( "/" );
var effectsAll = [
	"effects/effect-blind",
	"effects/effect-bounce",
	"effects/effect-clip",
	"effects/effect-drop",
	"effects/effect-explode",
	"effects/effect-fade",
	"effects/effect-fold",
	"effects/effect-highlight",
	"effects/effect-puff",
	"effects/effect-pulsate",
	"effects/effect-scale",
	"effects/effect-shake",
	"effects/effect-size",
	"effects/effect-slide",
	"effects/effect-transfer"
];
var widgets = [
	"accordion",
	"autocomplete",
	"button",
	"checkboxradio",
	"controlgroup",
	"datepicker",
	"dialog",
	"draggable",
	"droppable",
	"menu",
	"mouse",
	"progressbar",
	"resizable",
	"selectable",
	"selectmenu",
	"slider",
	"sortable",
	"spinner",
	"tabs",
	"tooltip"
];

function getPath( module ) {
	for ( var i = 0; i < widgets.length; i++ ) {
		if ( widgets[ i ] === module ) {
			return "widgets/" + module;
		}
	}
	for ( var j = 0; j < effectsAll.length; j++ ) {
		if ( module !== "effect" ) {
			if ( effectsAll[ j ] === module ) {
				return module;
			}
			if ( effectsAll[ j ].indexOf( module ) !== -1 ) {
				return "effects/" + module;
			}
		}
	}
	return module;
}
function fixPaths( modules ) {
	for ( var i = 0; i < modules.length; i++ ) {
		modules[ i ] = getPath( modules[ i ] );
	}
	return modules;
}

// Hide the page while things are loading to prevent a FOUC
document.documentElement.className = "demo-loading";

require.config( {
	baseUrl: window.location.pathname.indexOf( "demos/" ) !== -1 ? "../../ui" : "../../../ui",
	paths: {
		jquery: "../external/jquery/jquery",
		external: "../external/"
	},
	shim: {
		"external/globalize/globalize.culture.de-DE": [ "external/globalize/globalize" ],
		"external/globalize/globalize.culture.ja-JP": [ "external/globalize/globalize" ]
	}
} );

// Replace effects all shortcut modules with all the effects modules
if ( modules && modules.indexOf( "effects-all" ) !== -1 ) {
	modules = modules.replace( /effects-all/, effectsAll.join( " " ) );
}

modules = modules ? modules.replace( /^\s+|\s+$/g, "" ).split( /\s+/ ) : [];
if ( !composite ) {
	modules.push( pathParts[ pathParts.length - 2 ] );
}
modules = fixPaths( modules );

require( modules, function() {
	var newScript = document.createElement( "script" );

	document.documentElement.className = "";

	newScript.text = "( function() { " + script.innerHTML + " } )();";
	document.head.appendChild( newScript ).parentNode.removeChild( newScript );
} );

} )();
<commit_msg>Demos: Replace with ffb33daa229c62c7095cff39cde034f84ef54b15<commit_after>/* globals window, document */
( function() {

// Find the script element
var scripts = document.getElementsByTagName( "script" );
var script = scripts[ scripts.length - 1 ];

// Read the modules
var modules = script.getAttribute( "data-modules" );
var composite = script.getAttribute( "data-composite" ) || false;
var pathParts = window.location.pathname.split( "/" );
var effectsAll = [
	"effects/effect-blind",
	"effects/effect-bounce",
	"effects/effect-clip",
	"effects/effect-drop",
	"effects/effect-explode",
	"effects/effect-fade",
	"effects/effect-fold",
	"effects/effect-highlight",
	"effects/effect-puff",
	"effects/effect-pulsate",
	"effects/effect-scale",
	"effects/effect-shake",
	"effects/effect-size",
	"effects/effect-slide",
	"effects/effect-transfer"
];
var widgets = [
	"accordion",
	"autocomplete",
	"button",
	"checkboxradio",
	"controlgroup",
	"datepicker",
	"dialog",
	"draggable",
	"droppable",
	"menu",
	"mouse",
	"progressbar",
	"resizable",
	"selectable",
	"selectmenu",
	"slider",
	"sortable",
	"spinner",
	"tabs",
	"tooltip"
];

function getPath( module ) {
	for ( var i = 0; i < widgets.length; i++ ) {
		if ( widgets[ i ] === module ) {
			return "widgets/" + module;
		}
	}
	for ( var j = 0; j < effectsAll.length; j++ ) {
		if ( module !== "effect" ) {
			if ( effectsAll[ j ] === module ) {
				return module;
			}
			if ( effectsAll[ j ].indexOf( module ) !== -1 ) {
				return "effects/" + module;
			}
		}
	}
	return module;
}
function fixPaths( modules ) {
	for ( var i = 0; i < modules.length; i++ ) {
		modules[ i ] = getPath( modules[ i ] );
	}
	return modules;
}

// Hide the page while things are loading to prevent a FOUC
document.documentElement.className = "demo-loading";

require.config( {
	baseUrl: window.location.pathname.indexOf( "demos/" ) !== -1 ? "../../ui" : "../../../ui",
	paths: {
		jquery: "../external/jquery/jquery",
		external: "../external/"
	},
	shim: {
		"external/globalize/globalize.culture.de-DE": [ "external/globalize/globalize" ],
		"external/globalize/globalize.culture.ja-JP": [ "external/globalize/globalize" ]
	}
} );

// Replace effects all shortcut modules with all the effects modules
if ( modules && modules.indexOf( "effects-all" ) !== -1 ) {
	modules = modules.replace( /effects-all/, effectsAll.join( " " ) );
}

modules = modules ? modules.replace( /^\s+|\s+$/g, "" ).split( /\s+/ ) : [];
if ( !composite ) {
	modules.push( pathParts[ pathParts.length - 2 ] );
}
modules = fixPaths( modules );

require( modules, function() {
	var newScript = document.createElement( "script" );

	document.documentElement.className = "";

	newScript.text = "( function() { " + script.innerHTML + " } )();";
	document.body.appendChild( newScript ).parentNode.removeChild( newScript );
} );

} )();
<|endoftext|>


<commit_before>/*	Commands
	This is all the logic for binding commands (key presses, clicks, etc) to
	methods. bindCommands() should work on any object, Fiesta or not (though
	it does depend on other Fiesta methods).	*/

// Some config variables that probably don't change
var leftButton = 0;
if (Fiesta.getBrowser() === "Explorer")	leftButton = 1;
var rightButton = 2;
var middleButton = 1;
if (Fiesta.getBrowser() === "Explorer")	middleButton = 4;

// Bind commands to functions (works for any object)
Fiesta._leftclicks = [];
Fiesta._rightclicks = [];
Fiesta._middleclicks = [];
Fiesta._mousemoves = [];
Fiesta._keydowns = [];
Fiesta._keyups = [];
Fiesta.bindCommands = function(object, binds) {

	// This is an object, right?
	if (!(object instanceof Object))
		throw new TypeError(object + " is not an object; I can't bind things to it");

	// Are my modifiers all pressed (if I want them to be)?
	var modifiersPressed = function(str, key) {
		var desires = {
			shift: Fiesta.contains(str, "shift"),
			control: Fiesta.contains(str, "control") || Fiesta.contains(str, "ctrl"),
			alt: Fiesta.contains(str, "alt") || Fiesta.contains(str, "opt") || Fiesta.contains(str, "option"),
			meta: Fiesta.contains(str, "meta")
		};
		var shift = !desires.shift || key.shiftKey;
		var control = !desires.control || key.ctrlKey;
		var alt = !desires.alt || key.altKey;
		var meta = !desires.meta || key.metaKey;
		return (shift && control && alt && meta);
	};

	// Populate the different command types, find modifiers
	// If there's an error, we should keep going
	for (var i in binds) {
		try {
			switch (Fiesta.getEventType(i)) {
				case "leftclick":
					Fiesta._leftclicks.push(i);
					break;
				case "rightclick":
					Fiesta._rightclicks.push(i);
					break;
				case "middleclick":
					Fiesta._middleclicks.push(i);
					break;
				case "mousemove":
					Fiesta._mousemoves.push(i);
					break;
				case "keyup":
					Fiesta.getKeyCode(i);	// Makes sure error will be thrown
					Fiesta._keyups.push(i);
					break;
				case "keydown":
					Fiesta.getKeyCode(i);	// Makes sure error will be thrown
					Fiesta._keydowns.push(i);
					break;
			}
		} catch (e) {
			console.error(e);
		}
	}

	// Where am I binding to?
	var mouseBindTo = window;
	try {
		mouseBindTo = object.getPlayground().getDOMElement();
	} catch (_) {}
	var keyboardBindTo = window;

	// Bind right click to click, not left click
	mouseBindTo.oncontextmenu = function(mouse) {
		mouse.button = rightButton;
		mouseBindTo.onclick(mouse);
		return false;
	};

	// Do the bindings
	mouseBindTo.onmousemove = function(mouse) {
		for (var i in Fiesta._mousemoves) {
			binds[Fiesta._mousemoves[i]].call(object, mouse.clientX, mouse.clientY);
		}
	};
	mouseBindTo.onclick = function(mouse) {
		for (var i in Fiesta._leftclicks) {
			var leftPressed = (mouse.button == leftButton);
			var modifiers = modifiersPressed(Fiesta._leftclicks[i], mouse);
			if (leftPressed && modifiers)
				binds[Fiesta._leftclicks[i]].call(object, mouse.clientX, mouse.clientY);
		}
		for (var i in Fiesta._rightclicks) {
			var rightPressed = (mouse.button == rightButton);
			var modifiers = modifiersPressed(Fiesta._rightclicks[i], mouse);
			if (rightPressed && modifiers)
				binds[Fiesta._rightclicks[i]].call(object, mouse.clientX, mouse.clientY);
		}
		for (var i in Fiesta._middleclicks) {
			var middlePressed = (mouse.button == middleButton);
			var modifiers = modifiersPressed(Fiesta._middleclicks[i], mouse);
			if (middlePressed && modifiers)
				binds[Fiesta._middleclicks[i]].call(object, mouse.clientX, mouse.clientY);
		}
	};
	keyboardBindTo.onkeydown = function(key) {
		for (var i in Fiesta._keydowns) {
			var keyPressed = (key.keyCode == Fiesta.getKeyCode(Fiesta._keydowns[i]));
			var modifiers = modifiersPressed(Fiesta._keydowns[i], key);
			if (keyPressed && modifiers)
				binds[Fiesta._keydowns[i]].call(object);
		}
	};
	keyboardBindTo.onkeyup = function(key) {
		for (var i in Fiesta._keyups) {
			var keyPressed = (key.keyCode == Fiesta.getKeyCode(Fiesta._keyups[i]));
			var modifiers = modifiersPressed(Fiesta._keyups[i], key);
			if (keyPressed && modifiers)
				binds[Fiesta._keyups[i]].call(object);
		}
	};

};

// Extract event from command string
Fiesta.getEventType = function(str) {

	var command = str.split(" ").join("").toLowerCase();

	if (Fiesta.contains(command, "mouse") && Fiesta.contains(command, "move")) return "mousemove";
	if (Fiesta.contains(command, "click") && Fiesta.contains(command, "left")) return "leftclick";
	if (Fiesta.contains(command, "click") && Fiesta.contains(command, "right")) return "rightclick";
	if (Fiesta.contains(command, "click")) return Fiesta.DEFAULT_CLICK;
	if (Fiesta.contains(command, "keyup")) return "keyup";
	if (Fiesta.contains(command, "keydown")) return "keydown";

	try {	// We don't know what it is, so maybe it's the default keyboard command?
		Fiesta.getKeyCode(str);
		return Fiesta.DEFAULT_KEYBOARD_COMMAND;
	} catch (_) {
		throw new Error("Cannot find event type from " + str);
	}

};

// Change command name to keycode (simple)
Fiesta.getKeyCode = function(str) {
	var command = str.split(" ")[0].toLowerCase();
	if (Fiesta.contains(command, "+"))
		return Fiesta.getKeyCode(str.split("+")[1]);
	var translations = {
		"backspace": 8,
		"tab": 9,
		"enter": 13,
		"return": 13,
		"shift": 16,
		"control": 17,
		"ctrl": 17,
		"alt": 18,
		"opt": 18,
		"option": 18,
		"pause/break": 19,
		"pause": 19,
		"break": 19,
		"capslock": 20,
		"caps": 20,
		"escape": 27,
		"esc": 27,
		"space": 32,
		"spacebar": 32,
		"pageup": 33,
		"pgup": 33,
		"pagedown": 34,
		"pgdown": 34,
		"pagedn": 34,
		"pgdn": 34,
		"end": 35,
		"home": 36,
		"left": 37,
		"leftarrow": 37,
		"up": 38,
		"uparrow": 38,
		"right": 39,
		"rightarrow": 39,
		"down": 40,
		"downarrow": 40,
		"insert": 45,
		"ins": 45,
		"delete": 46,
		"del": 46,
		"0": 48,
		"1": 49,
		"2": 50,
		"3": 51,
		"4": 52,
		"5": 53,
		"6": 54,
		"7": 55,
		"8": 56,
		"9": 57,
		";": 59,
		":": 59,
		"=": 61,
		"+": 61,
		"a": 65,
		"b": 66,
		"c": 67,
		"d": 68,
		"e": 69,
		"f": 70,
		"g": 71,
		"h": 72,
		"i": 73,
		"j": 74,
		"k": 75,
		"l": 76,
		"m": 77,
		"n": 78,
		"o": 79,
		"p": 80,
		"q": 81,
		"r": 82,
		"s": 83,
		"t": 84,
		"u": 85,
		"v": 86,
		"w": 87,
		"x": 88,
		"y": 89,
		"z": 90,
		"f1": 112,
		"f2": 113,
		"f3": 114,
		"f4": 115,
		"f5": 116,
		"f6": 117,
		"f7": 118,
		"f8": 119,
		"f9": 120,
		"f10": 121,
		"f11": 122,
		"f12": 123,
		"windows": 91,
		"meta": 91,
		"apple": 91,
		"command": 91,
		"numlock": 144,
		"num": 144,
		"scrolllock": 145,
		"scroll": 145,
		"\\": 220,
		"|": 220,
		"[": 219,
		"{": 219,
		"]": 221,
		"}": 221,
		".": 190,
		">": 190,
		"/": 191,
		"?": 191,
		"`": 192,
		"~": 192,
		",": 188,
		"<": 188,
		"'": 222,
		"\"": 222
	};
	if (translations[command])
		return translations[command];
	else
		throw new Error(str + " cannot be translated to a keycode");
};<commit_msg>Major bugfix: Bind commands didn't work for multiple objects<commit_after>/*	Commands
	This is all the logic for binding commands (key presses, clicks, etc) to
	methods. bindCommands() should work on any object, Fiesta or not (though
	it does depend on other Fiesta methods).	*/

// Some config variables that probably don't change
var leftButton = 0;
if (Fiesta.getBrowser() === "Explorer")	leftButton = 1;
var rightButton = 2;
var middleButton = 1;
if (Fiesta.getBrowser() === "Explorer")	middleButton = 4;

// Bind commands to functions (works for any object)
Fiesta._leftclicks = [];
Fiesta._rightclicks = [];
Fiesta._middleclicks = [];
Fiesta._mousemoves = [];
Fiesta._keydowns = [];
Fiesta._keyups = [];
Fiesta.bindCommands = function(object, binds) {

	// This is an object, right?
	if (!(object instanceof Object))
		throw new TypeError(object + " is not an object; I can't bind things to it");

	// Are my modifiers all pressed (if I want them to be)?
	var modifiersPressed = function(str, key) {
		var desires = {
			shift: Fiesta.contains(str, "shift"),
			control: Fiesta.contains(str, "control") || Fiesta.contains(str, "ctrl"),
			alt: Fiesta.contains(str, "alt") || Fiesta.contains(str, "opt") || Fiesta.contains(str, "option"),
			meta: Fiesta.contains(str, "meta")
		};
		var shift = !desires.shift || key.shiftKey;
		var control = !desires.control || key.ctrlKey;
		var alt = !desires.alt || key.altKey;
		var meta = !desires.meta || key.metaKey;
		return (shift && control && alt && meta);
	};

	// Populate the different command types, find modifiers
	// If there's an error, we should keep going
	for (var i in binds) {
		try {
			switch (Fiesta.getEventType(i)) {
				case "leftclick":
					Fiesta._leftclicks.push(i);
					break;
				case "rightclick":
					Fiesta._rightclicks.push(i);
					break;
				case "middleclick":
					Fiesta._middleclicks.push(i);
					break;
				case "mousemove":
					Fiesta._mousemoves.push(i);
					break;
				case "keyup":
					Fiesta.getKeyCode(i);	// Makes sure error will be thrown
					Fiesta._keyups.push(i);
					break;
				case "keydown":
					Fiesta.getKeyCode(i);	// Makes sure error will be thrown
					Fiesta._keydowns.push(i);
					break;
			}
		} catch (e) {
			console.error(e);
		}
	}

	// Where am I binding to?
	var mouseBindTo = window;
	try {
		mouseBindTo = object.getPlayground().getDOMElement();
	} catch (_) {}
	var keyboardBindTo = window;

	// Bind right click to click, not left click
	mouseBindTo.oncontextmenu = function(mouse) {
		mouse.button = rightButton;
		mouseBindTo.onclick(mouse);
		return false;
	};

	// Get ready to bind! This function does cross-browser binding
	function addListener(element, event, fn) {
		if (element.addEventListener) {	// Everything else
			bubble = false;
			element.addEventListener(event, fn, bubble);
		} else if (this.attachEvent) {	// IE
			element.attachEvent("on" + event, fn);
		}
	}

	// Do the bindings
	addListener(mouseBindTo, "mousemove", function(mouse) {
		for (var i in Fiesta._mousemoves) {
			var modifiers = modifiersPressed(Fiesta._mousemoves[i], mouse);
			if (modifiers)
				binds[Fiesta._mousemoves[i]].call(object, mouse.clientX, mouse.clientY);
		}
	});
	addListener(mouseBindTo, "click", function(mouse) {
		for (var i in Fiesta._leftclicks) {
			var leftPressed = (mouse.button == leftButton);
			var modifiers = modifiersPressed(Fiesta._leftclicks[i], mouse);
			if (leftPressed && modifiers)
				binds[Fiesta._leftclicks[i]].call(object, mouse.clientX, mouse.clientY);
		}
		for (var i in Fiesta._rightclicks) {
			var rightPressed = (mouse.button == rightButton);
			var modifiers = modifiersPressed(Fiesta._rightclicks[i], mouse);
			if (rightPressed && modifiers)
				binds[Fiesta._rightclicks[i]].call(object, mouse.clientX, mouse.clientY);
		}
		for (var i in Fiesta._middleclicks) {
			var middlePressed = (mouse.button == middleButton);
			var modifiers = modifiersPressed(Fiesta._middleclicks[i], mouse);
			if (middlePressed && modifiers)
				binds[Fiesta._middleclicks[i]].call(object, mouse.clientX, mouse.clientY);
		}
	});
	addListener(keyboardBindTo, "keydown", function(key) {
		for (var i in Fiesta._keydowns) {
			var keyPressed = (key.keyCode == Fiesta.getKeyCode(Fiesta._keydowns[i]));
			var modifiers = modifiersPressed(Fiesta._keydowns[i], key);
			if (keyPressed && modifiers)
				binds[Fiesta._keydowns[i]].call(object);
		}
	});
	addListener(keyboardBindTo, "keyup", function(key) {
		for (var i in Fiesta._keyups) {
			var keyPressed = (key.keyCode == Fiesta.getKeyCode(Fiesta._keyups[i]));
			var modifiers = modifiersPressed(Fiesta._keyups[i], key);
			if (keyPressed && modifiers)
				binds[Fiesta._keyups[i]].call(object);
		}
	});

};

// Extract event from command string
Fiesta.getEventType = function(str) {

	var command = str.split(" ").join("").toLowerCase();

	if (Fiesta.contains(command, "mouse") && Fiesta.contains(command, "move")) return "mousemove";
	if (Fiesta.contains(command, "click") && Fiesta.contains(command, "left")) return "leftclick";
	if (Fiesta.contains(command, "click") && Fiesta.contains(command, "right")) return "rightclick";
	if (Fiesta.contains(command, "click")) return Fiesta.DEFAULT_CLICK;
	if (Fiesta.contains(command, "keyup")) return "keyup";
	if (Fiesta.contains(command, "keydown")) return "keydown";

	try {	// We don't know what it is, so maybe it's the default keyboard command?
		Fiesta.getKeyCode(str);
		return Fiesta.DEFAULT_KEYBOARD_COMMAND;
	} catch (_) {
		throw new Error("Cannot find event type from " + str);
	}

};

// Change command name to keycode (simple)
Fiesta.getKeyCode = function(str) {
	var command = str.split(" ")[0].toLowerCase();
	if (Fiesta.contains(command, "+"))
		return Fiesta.getKeyCode(str.split("+")[1]);
	var translations = {
		"backspace": 8,
		"tab": 9,
		"enter": 13,
		"return": 13,
		"shift": 16,
		"control": 17,
		"ctrl": 17,
		"alt": 18,
		"opt": 18,
		"option": 18,
		"pause/break": 19,
		"pause": 19,
		"break": 19,
		"capslock": 20,
		"caps": 20,
		"escape": 27,
		"esc": 27,
		"space": 32,
		"spacebar": 32,
		"pageup": 33,
		"pgup": 33,
		"pagedown": 34,
		"pgdown": 34,
		"pagedn": 34,
		"pgdn": 34,
		"end": 35,
		"home": 36,
		"left": 37,
		"leftarrow": 37,
		"up": 38,
		"uparrow": 38,
		"right": 39,
		"rightarrow": 39,
		"down": 40,
		"downarrow": 40,
		"insert": 45,
		"ins": 45,
		"delete": 46,
		"del": 46,
		"0": 48,
		"1": 49,
		"2": 50,
		"3": 51,
		"4": 52,
		"5": 53,
		"6": 54,
		"7": 55,
		"8": 56,
		"9": 57,
		";": 59,
		":": 59,
		"=": 61,
		"+": 61,
		"a": 65,
		"b": 66,
		"c": 67,
		"d": 68,
		"e": 69,
		"f": 70,
		"g": 71,
		"h": 72,
		"i": 73,
		"j": 74,
		"k": 75,
		"l": 76,
		"m": 77,
		"n": 78,
		"o": 79,
		"p": 80,
		"q": 81,
		"r": 82,
		"s": 83,
		"t": 84,
		"u": 85,
		"v": 86,
		"w": 87,
		"x": 88,
		"y": 89,
		"z": 90,
		"f1": 112,
		"f2": 113,
		"f3": 114,
		"f4": 115,
		"f5": 116,
		"f6": 117,
		"f7": 118,
		"f8": 119,
		"f9": 120,
		"f10": 121,
		"f11": 122,
		"f12": 123,
		"windows": 91,
		"meta": 91,
		"apple": 91,
		"command": 91,
		"numlock": 144,
		"num": 144,
		"scrolllock": 145,
		"scroll": 145,
		"\\": 220,
		"|": 220,
		"[": 219,
		"{": 219,
		"]": 221,
		"}": 221,
		".": 190,
		">": 190,
		"/": 191,
		"?": 191,
		"`": 192,
		"~": 192,
		",": 188,
		"<": 188,
		"'": 222,
		"\"": 222
	};
	if (translations[command])
		return translations[command];
	else
		throw new Error(str + " cannot be translated to a keycode");
};<|endoftext|>


<commit_before>/*
 * Originally taken from https://github.com/decker405/figwheel-react-native
 *
 * @providesModule figwheel-bridge
 */

var CLOSURE_UNCOMPILED_DEFINES = null;
var debugEnabled = false;

var config = {
    basePath: "target/",
    googBasePath: 'goog/',
    serverPort: 8081
};

var React = require('react');
var ReactNative = require('react-native');
var WebSocket = require('WebSocket');
var self;
var scriptQueue = [];
var serverHost = null; // will be set dynamically
var fileBasePath = null; // will be set dynamically
var evaluate = eval; // This is needed, direct calls to eval does not work (RN packager???)
var externalModules = {};
var evalListeners = [ // Functions to be called after each js file is loaded and evaluated
    function (url) {
        if (url.indexOf('jsloader') > -1) {
            shimJsLoader();
        }
    },
    function (url) {
        if (url.indexOf('/figwheel/client/socket') > -1) {
            setCorrectWebSocketImpl();
        }
    }];

var figwheelApp = function (platform, devHost) {
    return React.createClass({
        getInitialState: function () {
            return {loaded: false}
        },
        render: function () {
            if (!this.state.loaded) {
                var plainStyle = {flex: 1, alignItems: 'center', justifyContent: 'center'};
                return (
                    <ReactNative.View style={plainStyle}>
                        <ReactNative.Text>Waiting for Figwheel to load files.</ReactNative.Text>
                    </ReactNative.View>
                );
            }
            return this.state.root;
        },
        componentDidMount: function () {
            var app = this;
            if (typeof goog === "undefined") {
                loadApp(platform, devHost, function (appRoot) {
                    app.setState({root: appRoot, loaded: true})
                });
            }
        }
    })
};

function logDebug(msg) {
    if (debugEnabled) {
        console.log(msg);
    }
}

// evaluates js code ensuring proper ordering
function customEval(url, javascript, success, error) {
    if (scriptQueue.length > 0) {
        if (scriptQueue[0] === url) {
            try {
                evaluate(javascript);
                logDebug('Evaluated: ' + url);
                scriptQueue.shift();
                evalListeners.forEach(function (listener) {
                    listener(url)
                });
                success();
            } catch (e) {
                console.error(e);
                error();
            }
        } else {
            setTimeout(function () {
                customEval(url, javascript, success, error)
            }, 5);
        }
    } else {
        console.error('Something bad happened...');
        error()
    }
}

var isChrome = function () {
    return typeof importScripts === "function"
};

function asyncImportScripts(url, success, error) {
    logDebug('(asyncImportScripts) Importing: ' + url);
    scriptQueue.push(url);
    fetch(url)
        .then(function (response) {
            return response.text()
        })
        .then(function (responseText) {
            return customEval(url, responseText, success, error);
        })
        .catch(function (error) {
            console.error(error);
            return error();
        });
}

function syncImportScripts(url, success, error) {
    try {
        importScripts(url);
        logDebug('Evaluated: ' + url);
        evalListeners.forEach(function (listener) {
            listener(url)
        });
        success();
    } catch (e) {
        console.error(e);
        error()
    }
}

// Loads js file sync if possible or async.
function importJs(src, success, error) {
    if (typeof success !== 'function') {
        success = function () {
        };
    }
    if (typeof error !== 'function') {
        error = function () {
        };
    }

    var file = fileBasePath + '/' + src;

    logDebug('(importJs) Importing: ' + file);
    if (isChrome()) {
        syncImportScripts(serverBaseUrl("localhost") + '/' + file, success, error);
    } else {
        asyncImportScripts(serverBaseUrl(serverHost) + '/' + file, success, error);
    }
}

function interceptRequire() {
    var oldRequire = window.require;
    console.info("Shimming require");
    window.require = function (id) {
        console.info("Requiring: " + id);
        if (externalModules[id]) {
            return externalModules[id];
        }
        return oldRequire(id);
    };
}

function compileWarningsToYellowBox() {
    var log = window.console.log;
    var compileWarningRx = /Figwheel: Compile/;
    var compileExceptionRx = /Figwheel: Compile Exception/;
    var errorInFileRx = /Error on file/;
    var isBuffering = false;
    var compileExceptionBuffer = "";
    window.console.log = function (msg) {
        log.apply(window.console, arguments);
        if (compileExceptionRx.test(msg)) { // enter buffering mode to get all the messages for exception
            isBuffering = true;
            compileExceptionBuffer = msg + "\n";
        } else if (errorInFileRx.test(msg) && isBuffering) { // exit buffering mode and log buffered messages to YellowBox
            isBuffering = false;
            console.warn(compileExceptionBuffer + msg);
            compileExceptionBuffer = "";
        } else if (isBuffering) { //log messages buffering mode
            compileExceptionBuffer += msg + "\n";
        } else if (compileWarningRx.test(msg)) {
            console.warn(msg);
        }
    };
}

function serverBaseUrl(host) {
    return "http://" + host + ":" + config.serverPort
}

function setCorrectWebSocketImpl() {
    figwheel.client.socket.get_websocket_imp = function () {
        return WebSocket;
    };
}

function loadApp(platform, devHost, onLoadCb) {
    serverHost = devHost;
    fileBasePath = config.basePath + platform;

    // callback when app is ready to get the reloadable component
    var mainJs = '/env/' + platform + '/main.js';
    evalListeners.push(function (url) {
        if (url.indexOf(mainJs) > -1) {
            onLoadCb(env[platform].main.root_el);
            console.info('Done loading Clojure app');
        }
    });

    if (typeof goog === "undefined") {
        console.info('Loading Closure base.');
        interceptRequire();
        compileWarningsToYellowBox();
        importJs('goog/base.js', function () {
            shimBaseGoog();
            importJs('cljs_deps.js');
            importJs('goog/deps.js', function () {
                // This is needed because of RN packager
                // seriously React packager? why.
                var googreq = goog.require;

                googreq('figwheel.connect');
            });
        });
    }
}

function startApp(appName, platform, devHost) {
    ReactNative.AppRegistry.registerComponent(
        appName, () => figwheelApp(platform, devHost));
}

function withModules(moduleById) {
    externalModules = moduleById;
    return self;
}

// Goog fixes
function shimBaseGoog() {
    console.info('Shimming goog functions.');
    goog.basePath = 'goog/';
    goog.writeScriptSrcNode = importJs;
    goog.writeScriptTag_ = function (src, optSourceText) {
        importJs(src);
        return true;
    };
}

// Figwheel fixes
// Used by figwheel - uses importScript to load JS rather than <script>'s
function shimJsLoader() {
    console.info('==== Shimming jsloader ====');
    goog.net.jsloader.load = function (uri, options) {
        var deferred = {
            callbacks: [],
            errbacks: [],
            addCallback: function (cb) {
                deferred.callbacks.push(cb);
            },
            addErrback: function (cb) {
                deferred.errbacks.push(cb);
            },
            callAllCallbacks: function () {
                while (deferred.callbacks.length > 0) {
                    deferred.callbacks.shift()();
                }
            },
            callAllErrbacks: function () {
                while (deferred.errbacks.length > 0) {
                    deferred.errbacks.shift()();
                }
            }
        };

        // Figwheel needs this to be an async call,
        //    so that it can add callbacks to deferred
        setTimeout(function () {
            importJs(uri.getPath(),
                deferred.callAllCallbacks,
                deferred.callAllErrbacks);
        }, 1);

        return deferred;
    };
}

self = {
    withModules: withModules,
    start: startApp
};

module.exports = self;<commit_msg>Upgrades re-natal<commit_after>/*
 * Originally taken from https://github.com/decker405/figwheel-react-native
 *
 * @providesModule figwheel-bridge
 */

var CLOSURE_UNCOMPILED_DEFINES = null;
var debugEnabled = false;

var config = {
    basePath: "target/",
    googBasePath: 'goog/',
    serverPort: 8081
};

var React = require('react');
var ReactNative = require('react-native');
var WebSocket = require('WebSocket');
var self;
var scriptQueue = [];
var serverHost = null; // will be set dynamically
var fileBasePath = null; // will be set dynamically
var evaluate = eval; // This is needed, direct calls to eval does not work (RN packager???)
var externalModules = {};
var evalListeners = [ // Functions to be called after each js file is loaded and evaluated
    function (url) {
        if (url.indexOf('jsloader') > -1) {
            shimJsLoader();
        }
    },
    function (url) {
        if (url.indexOf('/figwheel/client/socket') > -1) {
            setCorrectWebSocketImpl();
        }
    }];

var figwheelApp = function (platform, devHost) {
    return React.createClass({
        getInitialState: function () {
            return {loaded: false}
        },
        render: function () {
            if (!this.state.loaded) {
                var plainStyle = {flex: 1, alignItems: 'center', justifyContent: 'center'};
                return (
                    <ReactNative.View style={plainStyle}>
                        <ReactNative.Text>Waiting for Figwheel to load files.</ReactNative.Text>
                    </ReactNative.View>
                );
            }
            return this.state.root;
        },
        componentDidMount: function () {
            var app = this;
            if (typeof goog === "undefined") {
                loadApp(platform, devHost, function (appRoot) {
                    app.setState({root: appRoot, loaded: true})
                });
            }
        }
    })
};

function logDebug(msg) {
    if (debugEnabled) {
        console.log(msg);
    }
}

// evaluates js code ensuring proper ordering
function customEval(url, javascript, success, error) {
    if (scriptQueue.length > 0) {
        if (scriptQueue[0] === url) {
            try {
                evaluate(javascript);
                logDebug('Evaluated: ' + url);
                scriptQueue.shift();
                evalListeners.forEach(function (listener) {
                    listener(url)
                });
                success();
            } catch (e) {
                console.error(e);
                error();
            }
        } else {
            setTimeout(function () {
                customEval(url, javascript, success, error)
            }, 5);
        }
    } else {
        console.error('Something bad happened...');
        error()
    }
}

var isChrome = function () {
    return typeof importScripts === "function"
};

function asyncImportScripts(url, success, error) {
    logDebug('(asyncImportScripts) Importing: ' + url);
    scriptQueue.push(url);
    fetch(url)
        .then(function (response) {
            return response.text()
        })
        .then(function (responseText) {
            return customEval(url, responseText, success, error);
        })
        .catch(function (error) {
            console.error(error);
            return error();
        });
}

function syncImportScripts(url, success, error) {
    try {
        importScripts(url);
        logDebug('Evaluated: ' + url);
        evalListeners.forEach(function (listener) {
            listener(url)
        });
        success();
    } catch (e) {
        console.error(e);
        error()
    }
}

// Loads js file sync if possible or async.
function importJs(src, success, error) {
    if (typeof success !== 'function') {
        success = function () {
        };
    }
    if (typeof error !== 'function') {
        error = function () {
        };
    }

    var file = fileBasePath + '/' + src;

    logDebug('(importJs) Importing: ' + file);
    if (isChrome()) {
        syncImportScripts(serverBaseUrl("localhost") + '/' + file, success, error);
    } else {
        asyncImportScripts(serverBaseUrl(serverHost) + '/' + file, success, error);
    }
}

function interceptRequire() {
    var oldRequire = window.require;
    console.info("Shimming require");
    window.require = function (id) {
        console.info("Requiring: " + id);
        if (externalModules[id]) {
            return externalModules[id];
        }
        return oldRequire(id);
    };
}

function compileWarningsToYellowBox() {
    var log = window.console.log;
    var compileWarningRx = /Figwheel: Compile/;
    var compileExceptionRx = /Figwheel: Compile Exception/;
    var errorInFileRx = /Error on file/;
    var isBuffering = false;
    var compileExceptionBuffer = "";
    window.console.log = function (msg) {
        log.apply(window.console, arguments);
        if (compileExceptionRx.test(msg)) { // enter buffering mode to get all the messages for exception
            isBuffering = true;
            compileExceptionBuffer = msg + "\n";
        } else if (errorInFileRx.test(msg) && isBuffering) { // exit buffering mode and log buffered messages to YellowBox
            isBuffering = false;
            console.warn(compileExceptionBuffer + msg);
            compileExceptionBuffer = "";
        } else if (isBuffering) { //log messages buffering mode
            compileExceptionBuffer += msg + "\n";
        } else if (compileWarningRx.test(msg)) {
            console.warn(msg);
        }
    };
}

function serverBaseUrl(host) {
    return "http://" + host + ":" + config.serverPort
}

function setCorrectWebSocketImpl() {
    figwheel.client.socket.get_websocket_imp = function () {
        return WebSocket;
    };
}

function loadApp(platform, devHost, onLoadCb) {
    serverHost = devHost;
    fileBasePath = config.basePath + platform;

    // callback when app is ready to get the reloadable component
    var mainJs = '/env/' + platform + '/main.js';
    evalListeners.push(function (url) {
        if (url.indexOf(mainJs) > -1) {
            onLoadCb(env[platform].main.root_el);
            console.info('Done loading Clojure app');
        }
    });

    if (typeof goog === "undefined") {
        console.info('Loading Closure base.');
        interceptRequire();
        compileWarningsToYellowBox();
        importJs('goog/base.js', function () {
            shimBaseGoog();
            importJs('cljs_deps.js');
            importJs('goog/deps.js', function () {
                // This is needed because of RN packager
                // seriously React packager? why.
                var googreq = goog.require;

                googreq('figwheel.connect.' + platform);
            });
        });
    }
}

function startApp(appName, platform, devHost) {
    ReactNative.AppRegistry.registerComponent(
        appName, () => figwheelApp(platform, devHost));
}

function withModules(moduleById) {
    externalModules = moduleById;
    return self;
}

// Goog fixes
function shimBaseGoog() {
    console.info('Shimming goog functions.');
    goog.basePath = 'goog/';
    goog.writeScriptSrcNode = importJs;
    goog.writeScriptTag_ = function (src, optSourceText) {
        importJs(src);
        return true;
    };
}

// Figwheel fixes
// Used by figwheel - uses importScript to load JS rather than <script>'s
function shimJsLoader() {
    console.info('==== Shimming jsloader ====');
    goog.net.jsloader.load = function (uri, options) {
        var deferred = {
            callbacks: [],
            errbacks: [],
            addCallback: function (cb) {
                deferred.callbacks.push(cb);
            },
            addErrback: function (cb) {
                deferred.errbacks.push(cb);
            },
            callAllCallbacks: function () {
                while (deferred.callbacks.length > 0) {
                    deferred.callbacks.shift()();
                }
            },
            callAllErrbacks: function () {
                while (deferred.errbacks.length > 0) {
                    deferred.errbacks.shift()();
                }
            }
        };

        // Figwheel needs this to be an async call,
        //    so that it can add callbacks to deferred
        setTimeout(function () {
            importJs(uri.getPath(),
                deferred.callAllCallbacks,
                deferred.callAllErrbacks);
        }, 1);

        return deferred;
    };
}

self = {
    withModules: withModules,
    start: startApp
};

module.exports = self;<|endoftext|>


<commit_before>/**
 * Created by Q on 4/1/2015.
 */
'use strict';

angular.module('transcoding-ui.view_history', ['ngRoute', 'ui.bootstrap', 'ngCookies'])

    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/history', {
            templateUrl: 'view_history/view_history.html',
            controller: 'ViewHistoryCtrl'
        });
    }])

    .controller('ViewHistoryCtrl', ['$scope','localStorageService','awsApiService','$window' ,function ($scope,localStorage,awsApi,$window) {
        $scope.files = {};
        $scope.timers = {};
        $scope.has_files = false;

        angular.forEach(localStorage.keys(), function( id){
            if(id!="user" && id!='sessionId'){
                awsApi.getFile(id).$promise.then(function(video) {
                    $scope.files[id] = video;
                    $scope.timers[id] = id;
                    $scope.has_files = true;
                });
            }
        });

        $scope.deleteFile = function(id){
            localStorage.remove(id);
            delete $scope.files[id];
        };

        $scope.updateProgress = function(id){
            awsApi.getFile(id).$promise.then(function(video) {
                $scope.files[id].progress = video.progress;
                $scope.files[id].mp4 = video.mp4;
                $scope.files[id].webm = video.webm;
            });
        };

        $scope.updateAll = function(){
            angular.forEach($scope.timers, function(name, id){
              if($scope.files[id].progress<100) {
                $scope.updateProgress(id);
              }else{
                delete $scope.timers[id];
              }
            });
        };
        setInterval($scope.updateAll,1000);

    }]);
<commit_msg>Added checking of key length before showing puppy<commit_after>/**
 * Created by Q on 4/1/2015.
 */
'use strict';

angular.module('transcoding-ui.view_history', ['ngRoute', 'ui.bootstrap', 'ngCookies'])

    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/history', {
            templateUrl: 'view_history/view_history.html',
            controller: 'ViewHistoryCtrl'
        });
    }])

    .controller('ViewHistoryCtrl', ['$scope','localStorageService','awsApiService','$window' ,function ($scope,localStorage,awsApi,$window) {
        $scope.files = {};
        $scope.timers = {};
        $scope.has_files = localStorage.keys().length>2;

        angular.forEach(localStorage.keys(), function( id){
            if(id!="user" && id!='sessionId'){
                awsApi.getFile(id).$promise.then(function(video) {
                    $scope.files[id] = video;
                    $scope.timers[id] = id;
                    $scope.has_files = true;
                });
            }
        });

        $scope.deleteFile = function(id){
            localStorage.remove(id);
            delete $scope.files[id];
            $scope.has_files = localStorage.keys().length>2;
        };

        $scope.updateProgress = function(id){
            awsApi.getFile(id).$promise.then(function(video) {
                $scope.files[id].progress = video.progress;
                $scope.files[id].mp4 = video.mp4;
                $scope.files[id].webm = video.webm;
            });
        };

        $scope.updateAll = function(){
            angular.forEach($scope.timers, function(name, id){
              if($scope.files[id].progress<100) {
                $scope.updateProgress(id);
              }else{
                delete $scope.timers[id];
              }
            });
        };
        setInterval($scope.updateAll,1000);

    }]);
<|endoftext|>