<commit_before>// Limits provided objects list
// Used for limiting business processes list for given user
// Should be invoked only once per list (which is guaranteed by memoization)

'use strict';

var memoize     = require('memoizee/weak-plain')
  , ensureArray = require('es5-ext/array/valid-array')
  , ensureSet   = require('es6-set/valid-set')
  , once        = require('timers-ext/once')

  , max = Math.max;

var normalize = function (list, applicable, preferred, limit) {
	var gap;

	list._postponed_ += 1;

	// Remove ones which do not belong
	list.forEach(function (object) {
		if (!applicable.has(object)) list.delete(object);
	});

	// Remove eventual oversize
	while (list.size > limit) list.delete(list.first);

	if (preferred) {
		// Fill if possible
		gap = max(limit - list.size, 0);
		if (gap) {
			preferred.some(function (object) {
				if (list.has(object)) return;
				list.add(object);
				if (!--gap) return true;
			});
			if (gap) {
				applicable.some(function (object) {
					if (list.has(object)) return;
					list.add(object);
					if (!--gap) return true;
				});
			}
		}
	}
	list._postponed_ -= 1;
};

module.exports = memoize(function (list, applicable/*, options*/) {
	var options = Object(arguments[1]), limit = Number(options.limit)
	  , preferred;
	if (isNaN(limit)) limit = 10;
	applicable = ensureSet(applicable);
	if (options.preferred != null) preferred = ensureArray(preferred);
	normalize(ensureSet(list), applicable, preferred, limit);
	list.on('change', once(function () { normalize(list, applicable, preferred, limit); }));
	return list;
}, { length: 1 });
<commit_msg>Fix options resolution<commit_after>// Limits provided objects list
// Used for limiting business processes list for given user
// Should be invoked only once per list (which is guaranteed by memoization)

'use strict';

var memoize     = require('memoizee/weak-plain')
  , ensureArray = require('es5-ext/array/valid-array')
  , ensureSet   = require('es6-set/valid-set')
  , once        = require('timers-ext/once')

  , max = Math.max;

var normalize = function (list, applicable, preferred, limit) {
	var gap;

	list._postponed_ += 1;

	// Remove ones which do not belong
	list.forEach(function (object) {
		if (!applicable.has(object)) list.delete(object);
	});

	// Remove eventual oversize
	while (list.size > limit) list.delete(list.first);

	if (preferred) {
		// Fill if possible
		gap = max(limit - list.size, 0);
		if (gap) {
			preferred.some(function (object) {
				if (list.has(object)) return;
				list.add(object);
				if (!--gap) return true;
			});
			if (gap) {
				applicable.some(function (object) {
					if (list.has(object)) return;
					list.add(object);
					if (!--gap) return true;
				});
			}
		}
	}
	list._postponed_ -= 1;
};

module.exports = memoize(function (list, applicable/*, options*/) {
	var options = Object(arguments[1]), limit = Number(options.limit)
	  , preferred;
	if (isNaN(limit)) limit = 10;
	applicable = ensureSet(applicable);
	if (options.preferred != null) preferred = ensureArray(options.preferred);
	normalize(ensureSet(list), applicable, preferred, limit);
	list.on('change', once(function () { normalize(list, applicable, preferred, limit); }));
	return list;
}, { length: 1 });
<|endoftext|>


<commit_before>export class BasicUse {
    attached() {
        const nodes = this.getNodes();
        this.tree.dataSource.load(nodes);
    }

    clearSelection() {
        // this.tree.clearSelection();
    }

    getNodes() {
        return [
            {
                title: 'Texas',
                children: [
                    { title: 'Austin' },
                    { title: 'Houston' }
                ]
            }, {
                title: 'New York',
                children: [
                    {
                        title: 'New York City',
                        children: [
                            { title: 'Manhattan' },
                            { title: 'Brooklyn' },
                            { title: 'Bronx' },
                            { title: 'Queens' },
                            { title: 'Staten Island' }
                        ]
                    }, {
                        title: 'Buffalo'
                    }
                ]
            }, {
                title: 'Oregon',
                children: [
                    { title: 'Portland' }
                ]
            }, {
                title: 'California',
                children: [
                    { title: 'Los Angeles' },
                    { title: 'San Francisco' }
                ]
            }
        ];
    }
}
<commit_msg>chore(sample): format code<commit_after>export class BasicUse {
  attached() {
    const nodes = this.getNodes();
    this.tree.dataSource.load(nodes);
  }

  clearSelection() {
    // this.tree.clearSelection();
  }

  getNodes() {
    return [
      {
        title: 'Texas',
        children: [
          { title: 'Austin' },
          { title: 'Houston' }
        ]
      }, {
        title: 'New York',
        children: [
          {
            title: 'New York City',
            children: [
              { title: 'Manhattan' },
              { title: 'Brooklyn' },
              { title: 'Bronx' },
              { title: 'Queens' },
              { title: 'Staten Island' }
            ]
          }, {
            title: 'Buffalo'
          }
        ]
      }, {
        title: 'Oregon',
        children: [
          { title: 'Portland' }
        ]
      }, {
        title: 'California',
        children: [
          { title: 'Los Angeles' },
          { title: 'San Francisco' }
        ]
      }
    ];
  }
}
<|endoftext|>


<commit_before>var roleHauler = {

	/** @param {Creep} creep **/
	run: function(creep) {

		if (creep.memory.harvesting) {
			var energy = creep.room.find(FIND_DROPPED_ENERGY, {
				filter: (res) => {
					return (res.amount > 50)
				}
			});

			if (energy.length == 0) {
				var storage = creep.room.find(FIND_STRUCTURES, {
					filter: (structure) => {
						return (
							(structure.structureType == STRUCTURE_CONTAINER) &&
							(structure.store[RESOURCE_ENERGY] > creep.carryCapacity) &&
							(structure.pos.findInRange(FIND_SOURCES, 2).length != 0));
					}
				});
				if (storage.length) {
					var target = creep.pos.findClosestByRange(storage);

					if (!(creep.pos.isNearTo(target))) {
						creep.moveTo(target);
					}
					else {
						creep.withdraw(target, RESOURCE_ENERGY,
													(creep.carryCapacity - _.sum(creep.carry)));
					}
				}
			}
			else {
				var target = creep.pos.findClosestByRange(energy);

				if (!(creep.pos.isNearTo(target))) {
					creep.moveTo(target);
				}
				else {
					creep.pickup(target);
				}
			}
			if (creep.carry.energy == creep.carryCapacity) {
				creep.say('Depositing');
		  	creep.memory.harvesting = false;
			}
		}
		else {
			var targets = creep.room.find(FIND_STRUCTURES, {
				filter: (structure) => {
					return (
								((structure.structureType == STRUCTURE_SPAWN) ||
								 (structure.structureType == STRUCTURE_EXTENSION)) &&
								 (structure.energy < structure.energyCapacity));
				}
			});

			if (targets.length == 0) {
				var targets = creep.room.find(FIND_STRUCTURES, {
					filter: (structure) => {
						return (
							((structure.structureType == STRUCTURE_CONTAINER) &&
								(_.sum(structure.store) < (structure.storeCapacity - creep.carry.energy)) &&
								structure.pos.findInRange(FIND_SOURCES, 2).length == 0));
					}
				});
			}
			if (targets.length == 0) {
				var targets = creep.room.find(FIND_STRUCTURES, {
					filter: (structure) => {
						return (
							(structure.structureType == STRUCTURE_STORAGE) &&
							(_.sum(structure.store) < structure.storeCapacity));
					}
				});
			}
			if (targets.length > 0) {
				var target = creep.pos.findClosestByRange(targets);
				if (creep.transfer(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
					creep.moveTo(target);
				}
			}
			if (creep.carry.energy < creep.carryCapacity) {
				creep.say('Harvesting');
			  creep.memory.harvesting = true;
			}
		}

	} // function

}; // roleHauler

module.exports = roleHauler;<commit_msg>Minor changes<commit_after>var roleHauler = {

	/** @param {Creep} creep **/
	run: function(creep) {

		if (creep.memory.harvesting) {
			var energy = creep.room.find(FIND_DROPPED_ENERGY, {
				filter: (res) => {
					return (res.amount > 50)
				}
			});

			if (energy.length == 0) {
				var storage = creep.room.find(FIND_STRUCTURES, {
					filter: (structure) => {
						return (
							(structure.structureType == STRUCTURE_CONTAINER) &&
							(structure.store[RESOURCE_ENERGY] > creep.carryCapacity) &&
							(structure.pos.findInRange(FIND_SOURCES, 2).length != 0));
					}
				});
				if (storage.length) {
					var target = creep.pos.findClosestByRange(storage);

					if (!(creep.pos.isNearTo(target))) {
						creep.moveTo(target);
					}
					else {
						creep.withdraw(target, RESOURCE_ENERGY,
													(creep.carryCapacity - _.sum(creep.carry)));
					}
				}
			}
			else {
				var target = creep.pos.findClosestByRange(energy);

				if (!(creep.pos.isNearTo(target))) {
					creep.moveTo(target);
				}
				else {
					creep.pickup(target);
				}
			}
			if (creep.carry.energy == creep.carryCapacity) {
				creep.say('Depositing');
		  	creep.memory.harvesting = false;
			}
		}
		else {
			var targets = creep.room.find(FIND_STRUCTURES, {
				filter: (structure) => {
					return (
								((structure.structureType == STRUCTURE_SPAWN) ||
								 (structure.structureType == STRUCTURE_EXTENSION)) &&
								 (structure.energy < structure.energyCapacity));
				}
			});

			if (targets.length == 0) {
				var targets = creep.room.find(FIND_STRUCTURES, {
					filter: (structure) => {
						return (
							((structure.structureType == STRUCTURE_CONTAINER) &&
								(_.sum(structure.store) < (structure.storeCapacity - creep.carry.energy)) &&
								structure.pos.findInRange(FIND_SOURCES, 2).length == 0));
					}
				});
			}
			if (targets.length == 0) {
				var targets = creep.room.find(FIND_STRUCTURES, {
					filter: (structure) => {
						return (
							(structure.structureType == STRUCTURE_STORAGE) &&
							(_.sum(structure.store) < structure.storeCapacity));
					}
				});
			}
			if (targets.length > 0) {
				var target = creep.pos.findClosestByRange(targets);
				if (creep.transfer(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
					creep.moveTo(target);
				}
			}
			if (creep.carry.energy == 0) {
				creep.say('Harvesting');
			  creep.memory.harvesting = true;
			}
		}

	} // function

}; // roleHauler

module.exports = roleHauler;<|endoftext|>


<commit_before>//Power is connected to pin4 (5V), ground is pin6, tx (output) is pin 8,
// rx (input) is pin10
var SerialPort = require('serialport').SerialPort;
console.log('Successfully loaded SerialPort module');

var serialPort = new SerialPort('/dev/ttyAMA0', {
	baudRate: 9600
});
console.log('Successfully initialised /dev/ttyAMA0');

serialPort.on('open', function () {
	console.log('Port is open')
	serialPort.on('data', function(msg) {
		console.log(msg.toString('ascii'));
	});
	serialPort.write(':SHello World to all\r');

var EMIC = (function() {

var emic = {};
emic.speak = function (data) {
	data = data.toString('ascii');
	if (data.length > 1000) {
		console.log('Error: Message exceeds the character limit');
	} else {
		//serialPort.write(':SHello World to all\r');
		serialPort.write(':S' + data + '\r');
		console.log(':S' + data + '\r');
	};
};

emic.demo = function (id) {
	id = id.toString('ascii');
	if (id == '0' || id == '1' || id == '2') {
		serialPort.write(':D' + id + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.stopNow = function () {
	serialPort.write(':X\r');
}

emic.pause = function () {
	serialPort.write(':Z\r');
};

emic.voice = function (id) {
	var idN = id.parseInt();
	if (idN >= 0 && idN <= 8) {
		id.toString('ascii');
		serialPort.write(':N' + id + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.volume = function (level) {
	var levelN = id.parseInt();
	if (levelN >= -48 && levelN <= 18) {
		level = level.toString('ascii');
		serialPort.write(':V' + level + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.rate = function (wpm) {
	var wpmN = wpm.parseInt();
	if (wpmN >= 75 && wpmN <= 600) {
		wpm = wpm.toString('ascii');
		serialPort.write(':W' + wpm + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.parser = function (id) {
	id = id.toString('ascii');
	if (parser == '0' || parser == '1' || parser == '2') {
		serialPort.write(':P' + id + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.revert = function () {
	serialPort.write(':R\r');
};

emic.callCurrentSettings = function () {
	serialPort.write(':C\r');
};

emic.callVersionInfo = function () {
	serialPort.write(':I\r');
};

emic.callCommands = function () {
	serialPort.write(':I\r');
};
return emic
}());

});
/*function writeLog(logFile, output){
	var logf = new File(logFile);
	logf.writeln(output);
	logf.close()*/

module.exports = EMIC;

<commit_msg>update<commit_after>//Power is connected to pin4 (5V), ground is pin6, tx (output) is pin 8,
// rx (input) is pin10

var EMIC = (function() {
var SerialPort = require('serialport').SerialPort;
console.log('Successfully loaded SerialPort module');

var serialPort = new SerialPort('/dev/ttyAMA0', {
	baudRate: 9600
});
console.log('Successfully initialised /dev/ttyAMA0');

serialPort.on('open', function () {
	console.log('Port is open')
	serialPort.on('data', function(msg) {
		console.log(msg.toString('ascii'));
	});
	serialPort.write(':SHello World to all\r');
});
var emic = {};
emic.speak = function (data) {
	data = data.toString('ascii');
	if (data.length > 1000) {
		console.log('Error: Message exceeds the character limit');
	} else {
		//serialPort.write(':SHello World to all\r');
		serialPort.write(':S' + data + '\r');
		console.log(':S' + data + '\r');
	};
};

emic.demo = function (id) {
	id = id.toString('ascii');
	if (id == '0' || id == '1' || id == '2') {
		serialPort.write(':D' + id + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.stopNow = function () {
	serialPort.write(':X\r');
}

emic.pause = function () {
	serialPort.write(':Z\r');
};

emic.voice = function (id) {
	var idN = id.parseInt();
	if (idN >= 0 && idN <= 8) {
		id.toString('ascii');
		serialPort.write(':N' + id + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.volume = function (level) {
	var levelN = id.parseInt();
	if (levelN >= -48 && levelN <= 18) {
		level = level.toString('ascii');
		serialPort.write(':V' + level + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.rate = function (wpm) {
	var wpmN = wpm.parseInt();
	if (wpmN >= 75 && wpmN <= 600) {
		wpm = wpm.toString('ascii');
		serialPort.write(':W' + wpm + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.parser = function (id) {
	id = id.toString('ascii');
	if (parser == '0' || parser == '1' || parser == '2') {
		serialPort.write(':P' + id + '\r');
	} else {
		console.log('Error: Invalid Command');
	};
};

emic.revert = function () {
	serialPort.write(':R\r');
};

emic.callCurrentSettings = function () {
	serialPort.write(':C\r');
};

emic.callVersionInfo = function () {
	serialPort.write(':I\r');
};

emic.callCommands = function () {
	serialPort.write(':I\r');
};
return emic
}());

/*function writeLog(logFile, output){
	var logf = new File(logFile);
	logf.writeln(output);
	logf.close()*/

module.exports = EMIC;

<|endoftext|>


<commit_before>'use strict';
/* Chatfilter, Namefilter (with hostfilter functionality)
 * By: jd, panpawn
 */

const fs = require('fs');

let adWhitelist = Config.adWhitelist ? Config.adWhitelist : [];
let adRegex = new RegExp("(play.pokemonshowdown.com\\/~~)(?!(" + adWhitelist.join('|') + "))", "g");

let bannedMessages = Config.bannedMessages ? Config.bannedMessages : [];

let watchPhrases = Config.watchPhrases ? Config.watchPhrases : [];
let watchUsers = Config.watchUsers ? Config.watchUsers : [];

/*********************
 * Chatfilter Magic *
 * ******************/

Config.chatfilter = function (message, user, room, connection, targetUser) {
	user.lastActiveTime = Date.now();
	if (!room && !Users(targetUser)) targetUser = {name: 'unknown user'};

	// watch phrases and watch users
	let watchRoom = Rooms('watchroom') ? Rooms('watchroom') : false;
	if (watchRoom) {
		let watchWords = watchPhrases.filter(phrase => { return ~toId(message).indexOf(phrase); }).length;
		let watchUserslist = watchUsers.filter(name => { return ~user.userid.indexOf(name); }).length;
		if (!user.can('hotpatch') && watchWords >= 1 || watchUserslist >= 1) {
			watchRoom.add('|c|' + user.getIdentity() + '| __(' + (room ? "To " + room.id : "Private message to " + targetUser.name) + ")__ " + message).update();
		}
	}

	// global banned messages
	for (let x in bannedMessages) {
		if (message.toLowerCase().indexOf(bannedMessages[x]) > -1 && bannedMessages[x] !== '' && message.substr(0, 1) !== '/') {
			if (user.locked) return false;
			Punishments.lock(user, Date.now() + 7 * 24 * 60 * 60 * 1000, "Said a banned word: " + bannedMessages[x]);
			user.popup('You have been automatically locked for sending a message containing a banned word.');
			Monitor.log('[PornMonitor]' + user.name + ' __(' + (room ? 'In ' + room.id : 'Private message to ' + targetUser.name) + ')__ was automatically locked for trying to say "' + message + '"');
			fs.appendFile('logs/modlog/modlog_staff.txt', '[' + (new Date().toJSON()) + '] (staff) ' + user.name + ' was locked from talking by the Server (' +
			bannedMessages[x] + ') (' + connection.ip + ')\n');
			Gold.pmUpperStaff(user.name + ' has been automatically locked for sending a message containing a banned word' +
			(room ? ". **Room:**" + room.id : " in a private message to " + targetUser.name + ".") + ' **Message:** ' + message, '~Server');
			return false;
		}
	}

	// advertising
	let pre_matches = (message.match(/psim|psim.us|psim us|psm.us|psm us/g) || []).length;
	let final_check = (pre_matches >= 1 ? adWhitelist.filter(server => { return ~message.indexOf(server); }).length : 0);
	if (!user.can('hotpatch') && (pre_matches >= 1 && final_check === 0 || pre_matches >= 2 && final_check >= 1 || message.match(adRegex))) {
		if (user.locked) return false;
		if (!user.advWarns) user.advWarns = 0;
		user.advWarns++;
		if (user.advWarns > 1) {
			Punishments.lock(user, Date.now() + 7 * 24 * 60 * 60 * 1000, "Advertising");
			fs.appendFile('logs/modlog/modlog_staff.txt', '[' + (new Date().toJSON()) + '] (staff) ' + user.name + ' was locked from talking by the Server. (Advertising) (' + connection.ip + ')\n');
			connection.sendTo(room, '|raw|You have been locked for attempting to advertise.');
			Gold.pmUpperStaff(user.name + " has been locked for attempting to advertise" + (room ? ". **Room:**" + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message, "~Server");
			Monitor.log(user.name + " has been locked for attempting to advertise" + (room ? ". **Room:** " + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message);
			return false;
		}
		Gold.pmUpperStaff(user.name + " has attempted to advertise" + (room ? ". **Room:** " + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message, "~Server");
		Monitor.log(user.name + " has attempted to advertise" + (room ? ". **Room:** " + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message);
		connection.sendTo(room, '|raw|Advertising detected, your message has not been sent and upper staff has been notified.' + '
Further attempts to advertise in a chat OR PMs will result in being locked');
		connection.user.popup("|modal|Advertising detected, your message has not been sent and upper staff has been notified.\n" + "Further attempts to advertise in a chat OR in PMs will result in being locked");
		return false;
	}
	return message;
};

/*********************
 * Namefilter Magic *
 * ******************/
try {
	Config.bannedNames = fs.readFileSync('config/bannednames.txt', 'utf8').toLowerCase().split('\n');
} catch (e) {
	Config.bannedNames = [];
}

function loadBannedNames() {
	try {
		Config.bannedNames = fs.readFileSync('config/bannednames.txt', 'utf8').toLowerCase().split('\n');
	} catch (e) {
		Config.bannedNames = [];
	}
}
loadBannedNames();

Config.namefilter = function (name, user) {
	let badNames = Config.bannedNames, badHosts = Object.keys(Gold.lockedHosts), nameId = toId(name);
	for (let x in badNames) {
		if (nameId.indexOf(badNames[x]) > -1 && badNames[x] !== '') {
			Monitor.log('[NameFilter] should probably FR: ' + name);
		}
	}

	// Hostfilter stuff
	let ip = user.connections[Object.keys(user.connections).length - 1].ip;

	// deal with global ranked user's manually...
	let userSymbol = (Users.usergroups[nameId] ? Users.usergroups[nameId].substr(0, 1) : ' ');
	let rankIndex = (Config.groupsranking.indexOf(userSymbol) ? Config.groupsranking.indexOf(userSymbol) : false);

	Dnsbl.reverse(ip).then(host => {
		if (!host) return;
		if (Config.proxyWhitelist.includes(nameId)) return;
		if (badHosts.length < 0) return; // there are no blacklisted hosts (yet)
		if (rankIndex && rankIndex > 0) return; // a hack for confirmed status from global auth

		badHosts.forEach(badHost => {
			if (host.includes(badHost)) {
				user.locked = '#hostfilter';
				user.updateIdentity();
				user.popup("|modal|You have been automatically locked due to being on a proxy known for spam and abuse.\n\nLog off PS! and try reconnecting without a proxy to be unlocked.");
				Monitor.log("[ProxyMonitor] " + name + " (" + ip + ") has been automatically locked. (" + host + ")");
				return;
			}
		});
	});

    return name;
};

/*********************
 * Hostfilter Magic *
 * ******************/
Gold.lockedHosts = Object.create(null);

function loadHostBlacklist () {
	fs.readFile('config/lockedhosts.json', 'utf8', function (err, file) {
		if (err) return;
		Gold.lockedHosts = JSON.parse(file);
	});
}
loadHostBlacklist();

function saveHost () {
	fs.writeFileSync('config/lockedhosts.json', JSON.stringify(Gold.lockedHosts));
}

exports.commands = {
	lockhost: function (target, room, user) {
		if (!this.can('pban')) return false;
		if (!target) return this.parse('/help lockhost');
		if (Gold.lockedHosts[target]) return this.errorReply("The host '" + target + "' is was already locked by " + Gold.lockedHosts[target].by + ".");

		Gold.lockedHosts[target] = {
			by: user.name,
			on: Date.now(),
		}
		saveHost();

		this.privateModCommand("(" + user.name + " has blacklisted host: " + target + ")");
	},
	lockhosthelp: ["/lockhost [host] - Adds host to server blacklist.  Users connecting with these hosts will be automatically locked from connection, so use this carefully! Requires & ~"],

	unlockhost: function (target, room, user) {
		if (!this.can('pban')) return false;
		if (!target) return this.parse('/help unlockhost');
		if (!Gold.lockedHosts[target]) return this.errorReply("The host '" + target + "' is not currently blacklisted.");

		delete Gold.lockedHosts[target];
		saveHost();

		this.privateModCommand("(" + user.name + " has unblacklisted host: " + target + ")");
	},
	unlockhosthelp: ["/unlockhost [host] - Removes a host from the server's blacklist.  Requires & ~"],

	proxylist: function (target, room, user) {
		if (!this.can('pban')) return false;
		let badHosts = Object.keys(Gold.lockedHosts);
		if (badHosts.length < 0) return this.errorReply("Weird, no proxies have been blacklisted (yet).");

		let buff = '

Proxy:	Blacklisted By:	Blacklisted:
';
		badHosts.forEach(proxy => {
			buff += '
' + proxy + '	' + Gold.lockedHosts[proxy].by + '	' + Tools.toDurationString(Date.now() - Gold.lockedHosts[proxy].on) + ' ago
';
		});

		return this.sendReplyBox(buff);
	}
};
<commit_msg>Chatfilter: fix lock parameters<commit_after>'use strict';
/* Chatfilter, Namefilter (with hostfilter functionality)
 * By: jd, panpawn
 */

const fs = require('fs');

let adWhitelist = Config.adWhitelist ? Config.adWhitelist : [];
let adRegex = new RegExp("(play.pokemonshowdown.com\\/~~)(?!(" + adWhitelist.join('|') + "))", "g");

let bannedMessages = Config.bannedMessages ? Config.bannedMessages : [];

let watchPhrases = Config.watchPhrases ? Config.watchPhrases : [];
let watchUsers = Config.watchUsers ? Config.watchUsers : [];

/*********************
 * Chatfilter Magic *
 * ******************/

Config.chatfilter = function (message, user, room, connection, targetUser) {
	user.lastActiveTime = Date.now();
	if (!room && !Users(targetUser)) targetUser = {name: 'unknown user'};

	// watch phrases and watch users
	let watchRoom = Rooms('watchroom') ? Rooms('watchroom') : false;
	if (watchRoom) {
		let watchWords = watchPhrases.filter(phrase => { return ~toId(message).indexOf(phrase); }).length;
		let watchUserslist = watchUsers.filter(name => { return ~user.userid.indexOf(name); }).length;
		if (!user.can('hotpatch') && watchWords >= 1 || watchUserslist >= 1) {
			watchRoom.add('|c|' + user.getIdentity() + '| __(' + (room ? "To " + room.id : "Private message to " + targetUser.name) + ")__ " + message).update();
		}
	}

	// global banned messages
	for (let x in bannedMessages) {
		if (message.toLowerCase().indexOf(bannedMessages[x]) > -1 && bannedMessages[x] !== '' && message.substr(0, 1) !== '/') {
			if (user.locked) return false;
			Punishments.lock(user, Date.now() + 7 * 24 * 60 * 60 * 1000, null, "Said a banned word: " + bannedMessages[x]);
			user.popup('You have been automatically locked for sending a message containing a banned word.');
			Monitor.log('[PornMonitor]' + user.name + ' __(' + (room ? 'In ' + room.id : 'Private message to ' + targetUser.name) + ')__ was automatically locked for trying to say "' + message + '"');
			fs.appendFile('logs/modlog/modlog_staff.txt', '[' + (new Date().toJSON()) + '] (staff) ' + user.name + ' was locked from talking by the Server (' +
			bannedMessages[x] + ') (' + connection.ip + ')\n');
			Gold.pmUpperStaff(user.name + ' has been automatically locked for sending a message containing a banned word' +
			(room ? ". **Room:**" + room.id : " in a private message to " + targetUser.name + ".") + ' **Message:** ' + message, '~Server');
			return false;
		}
	}

	// advertising
	let pre_matches = (message.match(/psim|psim.us|psim us|psm.us|psm us/g) || []).length;
	let final_check = (pre_matches >= 1 ? adWhitelist.filter(server => { return ~message.indexOf(server); }).length : 0);
	if (!user.can('hotpatch') && (pre_matches >= 1 && final_check === 0 || pre_matches >= 2 && final_check >= 1 || message.match(adRegex))) {
		if (user.locked) return false;
		if (!user.advWarns) user.advWarns = 0;
		user.advWarns++;
		if (user.advWarns > 1) {
			Punishments.lock(user, Date.now() + 7 * 24 * 60 * 60 * 1000, null, "Advertising");
			fs.appendFile('logs/modlog/modlog_staff.txt', '[' + (new Date().toJSON()) + '] (staff) ' + user.name + ' was locked from talking by the Server. (Advertising) (' + connection.ip + ')\n');
			connection.sendTo(room, '|raw|You have been locked for attempting to advertise.');
			Gold.pmUpperStaff(user.name + " has been locked for attempting to advertise" + (room ? ". **Room:**" + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message, "~Server");
			Monitor.log(user.name + " has been locked for attempting to advertise" + (room ? ". **Room:** " + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message);
			return false;
		}
		Gold.pmUpperStaff(user.name + " has attempted to advertise" + (room ? ". **Room:** " + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message, "~Server");
		Monitor.log(user.name + " has attempted to advertise" + (room ? ". **Room:** " + room.id : " in a private message to " + targetUser.name + ".") + " **Message:** " + message);
		connection.sendTo(room, '|raw|Advertising detected, your message has not been sent and upper staff has been notified.' + '
Further attempts to advertise in a chat OR PMs will result in being locked');
		connection.user.popup("|modal|Advertising detected, your message has not been sent and upper staff has been notified.\n" + "Further attempts to advertise in a chat OR in PMs will result in being locked");
		return false;
	}
	return message;
};

/*********************
 * Namefilter Magic *
 * ******************/
try {
	Config.bannedNames = fs.readFileSync('config/bannednames.txt', 'utf8').toLowerCase().split('\n');
} catch (e) {
	Config.bannedNames = [];
}

function loadBannedNames() {
	try {
		Config.bannedNames = fs.readFileSync('config/bannednames.txt', 'utf8').toLowerCase().split('\n');
	} catch (e) {
		Config.bannedNames = [];
	}
}
loadBannedNames();

Config.namefilter = function (name, user) {
	let badNames = Config.bannedNames, badHosts = Object.keys(Gold.lockedHosts), nameId = toId(name);
	for (let x in badNames) {
		if (nameId.indexOf(badNames[x]) > -1 && badNames[x] !== '') {
			Monitor.log('[NameFilter] should probably FR: ' + name);
		}
	}

	// Hostfilter stuff
	let ip = user.connections[Object.keys(user.connections).length - 1].ip;

	// deal with global ranked user's manually...
	let userSymbol = (Users.usergroups[nameId] ? Users.usergroups[nameId].substr(0, 1) : ' ');
	let rankIndex = (Config.groupsranking.indexOf(userSymbol) ? Config.groupsranking.indexOf(userSymbol) : false);

	Dnsbl.reverse(ip).then(host => {
		if (!host) return;
		if (Config.proxyWhitelist.includes(nameId)) return;
		if (badHosts.length < 0) return; // there are no blacklisted hosts (yet)
		if (rankIndex && rankIndex > 0) return; // a hack for confirmed status from global auth

		badHosts.forEach(badHost => {
			if (host.includes(badHost)) {
				user.locked = '#hostfilter';
				user.updateIdentity();
				user.popup("|modal|You have been automatically locked due to being on a proxy known for spam and abuse.\n\nLog off PS! and try reconnecting without a proxy to be unlocked.");
				Monitor.log("[ProxyMonitor] " + name + " (" + ip + ") has been automatically locked. (" + host + ")");
				return;
			}
		});
	});

    return name;
};

/*********************
 * Hostfilter Magic *
 * ******************/
Gold.lockedHosts = Object.create(null);

function loadHostBlacklist () {
	fs.readFile('config/lockedhosts.json', 'utf8', function (err, file) {
		if (err) return;
		Gold.lockedHosts = JSON.parse(file);
	});
}
loadHostBlacklist();

function saveHost () {
	fs.writeFileSync('config/lockedhosts.json', JSON.stringify(Gold.lockedHosts));
}

exports.commands = {
	lockhost: function (target, room, user) {
		if (!this.can('pban')) return false;
		if (!target) return this.parse('/help lockhost');
		if (Gold.lockedHosts[target]) return this.errorReply("The host '" + target + "' is was already locked by " + Gold.lockedHosts[target].by + ".");

		Gold.lockedHosts[target] = {
			by: user.name,
			on: Date.now(),
		}
		saveHost();

		this.privateModCommand("(" + user.name + " has blacklisted host: " + target + ")");
	},
	lockhosthelp: ["/lockhost [host] - Adds host to server blacklist.  Users connecting with these hosts will be automatically locked from connection, so use this carefully! Requires & ~"],

	unlockhost: function (target, room, user) {
		if (!this.can('pban')) return false;
		if (!target) return this.parse('/help unlockhost');
		if (!Gold.lockedHosts[target]) return this.errorReply("The host '" + target + "' is not currently blacklisted.");

		delete Gold.lockedHosts[target];
		saveHost();

		this.privateModCommand("(" + user.name + " has unblacklisted host: " + target + ")");
	},
	unlockhosthelp: ["/unlockhost [host] - Removes a host from the server's blacklist.  Requires & ~"],

	proxylist: function (target, room, user) {
		if (!this.can('pban')) return false;
		let badHosts = Object.keys(Gold.lockedHosts);
		if (badHosts.length < 0) return this.errorReply("Weird, no proxies have been blacklisted (yet).");

		let buff = '

Proxy:	Blacklisted By:	Blacklisted:
';
		badHosts.forEach(proxy => {
			buff += '
' + proxy + '	' + Gold.lockedHosts[proxy].by + '	' + Tools.toDurationString(Date.now() - Gold.lockedHosts[proxy].on) + ' ago
';
		});

		return this.sendReplyBox(buff);
	}
};
<|endoftext|>


<commit_before>module.exports = {
    list: require(__dirname + "/leaderboards.list.js"),
    save: require(__dirname + "/leaderboards.save.js"),
    saveAndList: require(__dirname + "/leaderboards.saveandlist.js")
};<commit_msg>Method name is case-sensitive<commit_after>module.exports = {
    list: require(__dirname + "/leaderboards.list.js"),
    save: require(__dirname + "/leaderboards.save.js"),
    saveandlist: require(__dirname + "/leaderboards.saveandlist.js")
};<|endoftext|>


<commit_before>var DB = require('./models.js');
/*
*  不同类型的消息路由功能
*
* */

var MESSAGES = {
    'LOGIN' : 'login',
    'CONTACT_LIST' : 'contact_list',
    'RECENTLY_LIST' : 'recently_list',
    'CHAT_MESSAGE' : 'chat_message'
};

// 登录消息  LOGIN
// 登录响应  LOGIN_RES
MESSAGES['LOGIN_RES'] = function(data){
    console.log(data);
    // 查询用户信息是不是正确
    var uid = data['uid'];
    DB.userModel.getUser(uid,function(err,res){
        if (err){
            console.log(err);
            return
        }

        // 处理用户信息

        console.log(res);
        return {'status': 'OK'};

    });
};

// 获取好友列表  CONTACT_LIST
// 获取好友列表响应  CONTACT_LIST_RES
MESSAGES['CONTACT_LIST_RES'] = function(data){
    var uid = data['uid'];
    DB.relationModel.find({ $or: [ {'uid_1': uid}, { 'uid_2': uid } ] }).exec(function(err,res){
        if (err){
            console.log(err);
            return
        }
        // 显示好友列表
        var uid_list = res;

        // 循环好友列表
        var uids = [];
        for(var i=0;i<uid_list.length;i++){
            if (uid_list[i]['uid_1']==uid){
                uids.push(uid_list[i]['uid_2']);
            }else{
                uids.push(uid_list[i]['uid_1']);
            }
        }
        // 查询批量用户的详细信息
        DB.userModel.find({ uid: { $in: uids} }).exec(function(err,res){
            if (err){
                console.log(err);
                return
            }
            console.log('好友列表详情',res);
            var contacts = res;
            return {'status': 'OK','contacts':contacts};
        });

    });
};

// 最近聊天   RECENTLY_LIST
// 最近聊天响应  RECENTLY_LIST_RES
MESSAGES['RECENTLY_LIST_RES'] = function(data){
    console.log(data);
    var contacts = [
        {
            'name':'Vaster',
            'avatar':'http://img1.2345.com/duoteimg/qqTxImg/2/78d4ee9b26cf134b72e6204fba2415f6.jpg',
            'message':'Hi, i am new here.',
            'time':'11:21',
            'uid' : '12'
        },{
            'name':'Tom',
            'avatar':'http://www.qq745.com/uploads/allimg/140825/1-140R5222015.jpg',
            'message':'No news is good news.',
            'time':'10:37',
            'uid' : '14'
        },{
            'name':'Jack',
            'avatar':'http://img.cnjiayu.net/3211573049-3310678237-21-0.jpg',
            'message':'Jack is a good boy.',
            'time':'09:15',
            'uid' : '15'
        },{
            'name':'Smite',
            'avatar':'http://img2.imgtn.bdimg.com/it/u=1963725967,863016856&fm=214&gp=0.jpg',
            'message':'Smite every day!',
            'time':'08:22',
            'uid' : '16'
        }
    ];
    return {'status': 'OK','contacts':contacts};
};

MESSAGES['CHAT_MESSAGE_RES'] = function(){

};

// 退出消息  LOGOUT

module.exports = MESSAGES;
<commit_msg>添加项目演示地址<commit_after>var DB = require('./models.js');
/*
*  不同类型的消息路由功能
*
* */

var MESSAGES = {
    'LOGIN' : 'login',
    'CONTACT_LIST' : 'contact_list',
    'RECENTLY_LIST' : 'recently_list',
    'CHAT_MESSAGE' : 'chat_message'
};

// 登录消息  LOGIN
// 登录响应  LOGIN_RES
MESSAGES['LOGIN_RES'] = function(data){
    console.log(data);
    // 查询用户信息是不是正确
    var uid = data['uid'];
    DB.userModel.getUser(uid,function(err,res){
        if (err){
            console.log(err);
            return
        }

        // 处理用户信息

        console.log(res);
        return {'status': 'OK'};

    });
};

// 获取好友列表  CONTACT_LIST
// 获取好友列表响应  CONTACT_LIST_RES
MESSAGES['CONTACT_LIST_RES'] = function(data){
    var uid = data['uid'];
    DB.relationModel.find({ $or: [ {'uid_1': uid}, { 'uid_2': uid } ] }).exec(function(err,res){
        if (err){
            console.log(err);
            return
        }
        // 显示好友列表
        var uid_list = res;

        // 循环好友列表
        var uids = [];
        for(var i=0;i<uid_list.length;i++){
            if (uid_list[i]['uid_1']==uid){
                uids.push(uid_list[i]['uid_2']);
            }else{
                uids.push(uid_list[i]['uid_1']);
            }
        }
        // 查询批量用户的详细信息
        DB.userModel.find({ uid: { $in: uids} }).exec(function(err,res){
            if (err){
                console.log(err);
                return
            }
            console.log('好友列表详情',res);
            var contacts = res;
            return {'status': 'OK','contacts':contacts};
        });
        return {'status': 'OK','contacts':[]};

    });
};

// 最近聊天   RECENTLY_LIST
// 最近聊天响应  RECENTLY_LIST_RES
MESSAGES['RECENTLY_LIST_RES'] = function(data){
    console.log(data);
    var contacts = [
        {
            'name':'Vaster',
            'avatar':'http://img1.2345.com/duoteimg/qqTxImg/2/78d4ee9b26cf134b72e6204fba2415f6.jpg',
            'message':'Hi, i am new here.',
            'time':'11:21',
            'uid' : '12'
        },{
            'name':'Tom',
            'avatar':'http://www.qq745.com/uploads/allimg/140825/1-140R5222015.jpg',
            'message':'No news is good news.',
            'time':'10:37',
            'uid' : '14'
        },{
            'name':'Jack',
            'avatar':'http://img.cnjiayu.net/3211573049-3310678237-21-0.jpg',
            'message':'Jack is a good boy.',
            'time':'09:15',
            'uid' : '15'
        },{
            'name':'Smite',
            'avatar':'http://img2.imgtn.bdimg.com/it/u=1963725967,863016856&fm=214&gp=0.jpg',
            'message':'Smite every day!',
            'time':'08:22',
            'uid' : '16'
        }
    ];
    return {'status': 'OK','contacts':contacts};
};

MESSAGES['CHAT_MESSAGE_RES'] = function(){

};

// 退出消息  LOGOUT

module.exports = MESSAGES;
<|endoftext|>


<commit_before>/*
 * chesterGL - Simple 2D WebGL demo/library
 *
 * Copyright (c) 2010-2012 Rolando Abarca
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

goog.provide("chesterGL.BlockGroup");

goog.require("goog.vec.Mat4");
goog.require("chesterGL.Block");

/**
 * creates a new block group
 *
 * @constructor
 * @param {(string|null)=} texture An optional texture that will be shared with all children
 * @param {number=} noChildren The optional initial number of maxChidlren. Defaults to 10
 * @extends {chesterGL.Block}
 */
chesterGL.BlockGroup = function (texture, noChildren) {
	if (!chesterGL.webglMode) {
		throw "BlockGroup only works on WebGL mode";
	}
	// call "super"
	chesterGL.Block.call(this, null, chesterGL.Block.TYPE['BLOCKGROUP']);
	if (texture) {
		this.texture = texture;
		this.program = chesterGL.Block.PROGRAM['TEXTURE'];
	} else {
		this.program = chesterGL.Block.PROGRAM['DEFAULT'];
	}
	this.maxChildren = noChildren || 10;

	// create the buffers for the children
	this.createBuffers();
};
goog.inherits(chesterGL.BlockGroup, chesterGL.Block);

/**
 * The max number of children this blockgroup can hold (this is here for the buffer data)
 * @type {number}
 * @ignore
 */
chesterGL.BlockGroup.prototype.maxChildren = 0;

/**
 * @type {boolean}
 * @ignore
 */
chesterGL.BlockGroup.prototype.isChildDirty = false;

/**
 * @type {?WebGLBuffer}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBuffer = null;

/**
 * @type {?Uint16Array}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBufferData = null;

/**
 * Creates the buffers for the current maxChildren size
 * @param {Array|Float32Array=} oldBufferData
 * @param {Array|Uint16Array=} oldIndexData
 * @ignore
 */
chesterGL.BlockGroup.prototype.createBuffers = function (oldBufferData, oldIndexData) {
	var gl = chesterGL.gl;
	if (!this.glBuffer)
		this.glBuffer = gl.createBuffer();
	if (!this.indexBuffer)
		this.indexBuffer = gl.createBuffer();

	var glBufferData    = new Float32Array(chesterGL.Block.QUAD_SIZE * this.maxChildren);
	var indexBufferData = new Uint16Array(6 * this.maxChildren);
	if (oldBufferData) {
		glBufferData.set(oldBufferData);
	}
	if (oldIndexData) {
		indexBufferData.set(oldIndexData);
	}
	this.glBufferData = glBufferData;
	this.indexBufferData = indexBufferData;
};

/**
 * creates a block that can be added to this block group
 * @param {goog.vec.Vec4.Type} rect
 */
chesterGL.BlockGroup.prototype.createBlock = function (rect) {
	var b = new chesterGL.Block(rect, chesterGL.Block.TYPE['STANDALONE'], this);
	if (this.texture) {
		b.setTexture(this.texture);
	}
	return b;
};

/**
 * adds a child
 * @param {chesterGL.Block} block
 */
chesterGL.BlockGroup.prototype.addChild = function (block) {
	if (block.parent != this) {
		throw "Invalid child: can only add children created with BlockGroup.create";
	}
	if (this.children.length >= this.maxChildren) {
		// should resize the buffers
		this.maxChildren *= 2;
		this.createBuffers(this.glBufferData, this.indexBufferData);
	}
	if (!this.texture) {
		this.texture = block.texture;
	} else {
		if (this.texture != block.texture) {
			throw "Invalid child: only can add child with the same texture";
		}
	}
	this.children.push(block);

	var length = this.children.length;

	// just point the buffer data on the child and set the baseIndex
	block.baseBufferIndex = length-1;
	block.glBufferData    = this.glBufferData;
	this.isChildDirty = true;
};

/**
 * removes a block from the group
 * @param {chesterGL.Block} b
 */
chesterGL.BlockGroup.prototype.removeChild = function (b) {
	if (b.parent != this) {
		throw "Invalid child";
	}
	if (this._inVisit) {
		this._scheduledRemove.push(b);
	} else {
		var idx = this.children.indexOf(b);
		if (idx > 0) {
			this.children.splice(idx, 1);
			// for the rest of the children, mark them as dirty and reduce the baseBufferIndex
			for (var i=idx; i < this.totalChildren; i++) {
				var _b = this.children[i];
				_b.baseBufferIndex = i;
				_b.isTransformDirty = true;
				_b.isColorDirty = true;
			}
		}
		this.isChildDirty = true;
	}
};

/**
 * when the block list changes, the indices array must be recreated
 * @param {number} startIdx
 */
chesterGL.BlockGroup.prototype.recreateIndices = function (startIdx) {
	var lastIdx = (this.indexBufferData[startIdx*6 - 1] || -1) + 1;
	var total = Math.max(this.children.length, 1);
	for (var i = startIdx; i < total; i ++) {
		var idx = i*6;
		this.indexBufferData[idx + 0] = lastIdx    ; this.indexBufferData[idx + 1] = lastIdx + 1; this.indexBufferData[idx + 2] = lastIdx + 2;
		this.indexBufferData[idx + 3] = lastIdx + 2; this.indexBufferData[idx + 4] = lastIdx + 1; this.indexBufferData[idx + 5] = lastIdx + 3;
		lastIdx += 4;
	}
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexBufferData, gl.STATIC_DRAW);
};

/**
 * where the fun begins
 * @ignore
 */
chesterGL.BlockGroup.prototype.visit = function () {
	this._inVisit = true;
	if (this.update) {
		this.update(chesterGL.delta);
	}
	if (!this.visible) {
		this._inVisit = false;
		return;
	}
	this.transform();

	// this should be more like cocos2d: preserve the z-ordering
	var children = this.children;
	var len = children.length;
	for (var i=0; i < len; i++) {
		children[i].visit();
	}

	// re-bind the glBuffer (might have changed in the children visit)
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, this.glBufferData, gl.STATIC_DRAW);

	if (this.isChildDirty) {
		this.recreateIndices(0);
		this.isChildDirty = false;
	}
	// render this block group
	this.render();

	// reset our dirty markers
	this.isFrameDirty = this.isColorDirty = this.isTransformDirty = false;
	this._inVisit = false;

	var b;
	while (b = this._scheduledRemove.shift()) {
		this.removeChild(b);
	}
};

/**
 * actually render the block group
 * @ignore
 */
chesterGL.BlockGroup.prototype.render = function () {
	var gl = chesterGL.gl;

	// select current shader
	var program = chesterGL.selectProgram(chesterGL.Block.PROGRAM_NAME[this.program]);
	var totalChildren = this.children.length;
	var texOff = 3 * 4,
		colorOff = texOff + 2 * 4,
		stride = chesterGL.Block.QUAD_SIZE;

	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);

	gl.vertexAttribPointer(program.attribs['vertexPositionAttribute'], 3, gl.FLOAT, false, stride, 0);
	if (this.program == chesterGL.Block.PROGRAM['DEFAULT']) {
		// no extra attributes for the shader
	} else if (this.program == chesterGL.Block.PROGRAM['TEXTURE']) {
		var texture = chesterGL.getAsset('texture', this.texture);

		// pass the texture attributes
		gl.vertexAttribPointer(program.attribs['textureCoordAttribute'], 2, gl.FLOAT, false, stride, texOff);

		gl.activeTexture(gl.TEXTURE0);
		gl.bindTexture(gl.TEXTURE_2D, texture.tex);
		gl.uniform1i(program.samplerUniform, 0);
	}
	gl.vertexAttribPointer(program.attribs['vertexColorAttribute'], 4, gl.FLOAT, false, stride, colorOff);

	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);

	// set the matrix uniform (the multiplied model view projection matrix)
	goog.vec.Mat4.multMat(chesterGL.pMatrix, this.mvMatrix, this.mvpMatrix);
	gl.uniformMatrix4fv(program.mvpMatrixUniform, false, this.mvpMatrix);
	// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4 * this.children.length);
	gl.drawElements(gl.TRIANGLES, totalChildren * 6, gl.UNSIGNED_SHORT, 0);
};

// export the symbol
goog.exportSymbol('chesterGL.BlockGroup', chesterGL.BlockGroup);
// instance methods
goog.exportProperty(chesterGL.BlockGroup.prototype, 'createBlock', chesterGL.BlockGroup.prototype.createBlock);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'addChild', chesterGL.BlockGroup.prototype.addChild);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'removeChild', chesterGL.BlockGroup.prototype.removeChild);
<commit_msg>just some formatting<commit_after>/*
 * chesterGL - Simple 2D WebGL demo/library
 *
 * Copyright (c) 2010-2012 Rolando Abarca
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

goog.provide("chesterGL.BlockGroup");

goog.require("goog.vec.Mat4");
goog.require("chesterGL.Block");

/**
 * creates a new block group
 *
 * @constructor
 * @param {(string|null)=} texture An optional texture that will be shared with all children
 * @param {number=} noChildren The optional initial number of maxChidlren. Defaults to 10
 * @extends {chesterGL.Block}
 */
chesterGL.BlockGroup = function (texture, noChildren) {
	if (!chesterGL.webglMode) {
		throw "BlockGroup only works on WebGL mode";
	}
	// call "super"
	chesterGL.Block.call(this, null, chesterGL.Block.TYPE['BLOCKGROUP']);
	if (texture) {
		this.texture = texture;
		this.program = chesterGL.Block.PROGRAM['TEXTURE'];
	} else {
		this.program = chesterGL.Block.PROGRAM['DEFAULT'];
	}
	this.maxChildren = noChildren || 10;

	// create the buffers for the children
	this.createBuffers();
};
goog.inherits(chesterGL.BlockGroup, chesterGL.Block);

/**
 * The max number of children this blockgroup can hold (this is here for the buffer data)
 * @type {number}
 * @ignore
 */
chesterGL.BlockGroup.prototype.maxChildren = 0;

/**
 * @type {boolean}
 * @ignore
 */
chesterGL.BlockGroup.prototype.isChildDirty = false;

/**
 * @type {?WebGLBuffer}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBuffer = null;

/**
 * @type {?Uint16Array}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBufferData = null;

/**
 * Creates the buffers for the current maxChildren size
 * @param {Array|Float32Array=} oldBufferData
 * @param {Array|Uint16Array=} oldIndexData
 * @ignore
 */
chesterGL.BlockGroup.prototype.createBuffers = function (oldBufferData, oldIndexData) {
	var gl = chesterGL.gl;
	if (!this.glBuffer)
		this.glBuffer = gl.createBuffer();
	if (!this.indexBuffer)
		this.indexBuffer = gl.createBuffer();

	var glBufferData    = new Float32Array(chesterGL.Block.QUAD_SIZE * this.maxChildren);
	var indexBufferData = new Uint16Array(6 * this.maxChildren);
	if (oldBufferData) {
		glBufferData.set(oldBufferData);
	}
	if (oldIndexData) {
		indexBufferData.set(oldIndexData);
	}
	this.glBufferData = glBufferData;
	this.indexBufferData = indexBufferData;
};

/**
 * creates a block that can be added to this block group
 * @param {goog.vec.Vec4.Type} rect
 */
chesterGL.BlockGroup.prototype.createBlock = function (rect) {
	var b = new chesterGL.Block(rect, chesterGL.Block.TYPE['STANDALONE'], this);
	if (this.texture) {
		b.setTexture(this.texture);
	}
	return b;
};

/**
 * adds a child
 * @param {chesterGL.Block} block
 */
chesterGL.BlockGroup.prototype.addChild = function (block) {
	if (block.parent != this) {
		throw "Invalid child: can only add children created with BlockGroup.create";
	}
	if (this.children.length >= this.maxChildren) {
		// should resize the buffers
		this.maxChildren *= 2;
		this.createBuffers(this.glBufferData, this.indexBufferData);
	}
	if (!this.texture) {
		this.texture = block.texture;
	} else {
		if (this.texture != block.texture) {
			throw "Invalid child: only can add child with the same texture";
		}
	}
	this.children.push(block);

	var length = this.children.length;

	// just point the buffer data on the child and set the baseIndex
	block.baseBufferIndex = length-1;
	block.glBufferData    = this.glBufferData;
	this.isChildDirty = true;
};

/**
 * removes a block from the group
 * @param {chesterGL.Block} b
 */
chesterGL.BlockGroup.prototype.removeChild = function (b) {
	if (b.parent != this) {
		throw "Invalid child";
	}
	if (this._inVisit) {
		this._scheduledRemove.push(b);
	} else {
		var idx = this.children.indexOf(b);
		if (idx > 0) {
			this.children.splice(idx, 1);
			// for the rest of the children, mark them as dirty and reduce the baseBufferIndex
			for (var i=idx; i < this.totalChildren; i++) {
				var _b = this.children[i];
				_b.baseBufferIndex = i;
				_b.isTransformDirty = true;
				_b.isColorDirty = true;
			}
		}
		this.isChildDirty = true;
	}
};

/**
 * when the block list changes, the indices array must be recreated
 * @param {number} startIdx
 */
chesterGL.BlockGroup.prototype.recreateIndices = function (startIdx) {
	var lastIdx = (this.indexBufferData[startIdx*6 - 1] || -1) + 1;
	var total = Math.max(this.children.length, 1);
	for (var i = startIdx; i < total; i ++) {
		var idx = i*6;
		this.indexBufferData[idx + 0] = lastIdx    ; this.indexBufferData[idx + 1] = lastIdx + 1; this.indexBufferData[idx + 2] = lastIdx + 2;
		this.indexBufferData[idx + 3] = lastIdx + 2; this.indexBufferData[idx + 4] = lastIdx + 1; this.indexBufferData[idx + 5] = lastIdx + 3;
		lastIdx += 4;
	}
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexBufferData, gl.STATIC_DRAW);
};

/**
 * where the fun begins
 * @ignore
 */
chesterGL.BlockGroup.prototype.visit = function () {
	this._inVisit = true;
	if (this.update) {
		this.update(chesterGL.delta);
	}
	if (!this.visible) {
		this._inVisit = false;
		return;
	}
	this.transform();

	// this should be more like cocos2d: preserve the z-ordering
	var children = this.children;
	var len = children.length;
	for (var i=0; i < len; i++) {
		children[i].visit();
	}

	// re-bind the glBuffer (might have changed in the children visit)
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, this.glBufferData, gl.STATIC_DRAW);

	if (this.isChildDirty) {
		this.recreateIndices(0);
		this.isChildDirty = false;
	}
	// render this block group
	this.render();

	// reset our dirty markers
	this.isFrameDirty = this.isColorDirty = this.isTransformDirty = false;
	this._inVisit = false;

	var b;
	while ((b = this._scheduledRemove.shift())) {
		this.removeChild(b);
	}
};

/**
 * actually render the block group
 * @ignore
 */
chesterGL.BlockGroup.prototype.render = function () {
	var gl = chesterGL.gl;

	// select current shader
	var program = chesterGL.selectProgram(chesterGL.Block.PROGRAM_NAME[this.program]);
	var totalChildren = this.children.length;
	var texOff = 3 * 4,
		colorOff = texOff + 2 * 4,
		stride = chesterGL.Block.QUAD_SIZE;

	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);

	gl.vertexAttribPointer(program.attribs['vertexPositionAttribute'], 3, gl.FLOAT, false, stride, 0);
	if (this.program == chesterGL.Block.PROGRAM['DEFAULT']) {
		// no extra attributes for the shader
	} else if (this.program == chesterGL.Block.PROGRAM['TEXTURE']) {
		var texture = chesterGL.getAsset('texture', this.texture);

		// pass the texture attributes
		gl.vertexAttribPointer(program.attribs['textureCoordAttribute'], 2, gl.FLOAT, false, stride, texOff);

		gl.activeTexture(gl.TEXTURE0);
		gl.bindTexture(gl.TEXTURE_2D, texture.tex);
		gl.uniform1i(program.samplerUniform, 0);
	}
	gl.vertexAttribPointer(program.attribs['vertexColorAttribute'], 4, gl.FLOAT, false, stride, colorOff);

	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);

	// set the matrix uniform (the multiplied model view projection matrix)
	goog.vec.Mat4.multMat(chesterGL.pMatrix, this.mvMatrix, this.mvpMatrix);
	gl.uniformMatrix4fv(program.mvpMatrixUniform, false, this.mvpMatrix);
	// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4 * this.children.length);
	gl.drawElements(gl.TRIANGLES, totalChildren * 6, gl.UNSIGNED_SHORT, 0);
};

// export the symbol
goog.exportSymbol('chesterGL.BlockGroup', chesterGL.BlockGroup);
// instance methods
goog.exportProperty(chesterGL.BlockGroup.prototype, 'createBlock', chesterGL.BlockGroup.prototype.createBlock);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'addChild', chesterGL.BlockGroup.prototype.addChild);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'removeChild', chesterGL.BlockGroup.prototype.removeChild);
<|endoftext|>


<commit_before>// ==UserScript==
// @name            Redirector
// @author          xiaoxiaoflood
// @include         main
// @shutdown        UC.Redirector.destroy();
// @onlyonce
// ==/UserScript==

// inspired by: https://github.com/harv/userChromeJS/blob/master/redirector_ui.uc.js

UC.Redirector = {

  // [regex, replace, decode, tld]
  rules: [[
    /^https?:\/\/redir\.folha\.com\.br\/redir\/online\/.+?\*(.+)/,
    '$1',
    true
  ], [
    /^https?:\/\/www\.google\.tld\/url\?(?:.*&)?(?:url|q)=([^&#]+).*/,
    '$1',
    true,
    true
  ], [
    /^https?:\/\/www\.google\.tld\/imgres\?imgurl=([^&#]+).*/,
    '$1',
    true,
    true
  ], [
    /^https:\/\/outgoing\.prod\.mozaws\.net\/v1\/\w+\/(.+)/,
    '$1',
    true
  ], [
    /^https?:\/\/click\.uol\.com\.br\/\?(?:.*&)?u=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/(?:(?:m|new)\.)?vk\.com\/away\.php\?(?:.*&)?to=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/l\.instagram\.com\/\?(?:.*&)?u=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/www\.youtube\.com\/redirect\?(?:.*&)?q=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/www\.reddit\.com\/u(?:(?:ser\/([^\/]+)\/?$)|\/(?:([^\/]+)\/?$|(.*)))/,
    function (url) {
      return 'https://www.reddit.com/user/' + (url[3] ? url[3] : (url[1] || url[2]) + '/overview/');
    }
  ], [
    /^https?:\/\/bugzil\.la\/(.*)/,
    function (url) {
      return 'https://bugzilla.mozilla.org/' + (url[1] ? 'show_bug.cgi?id=' + url[1] : '');
    }
  ], [
    /^https?:\/\/youtu\.be\/(.*)/,
    function (url) {
      return 'https://www.youtube.com/' + (url[1] ? 'watch?v=' + url[1] : '');
    }
  ], [
    /^https?:\/\/(userscripts\.org(?:\:8080|)|(?:www.|)webextender.net)\/(.*)/,
    'http://userscripts-mirror.org/$2'
  ], [
    /^http:\/\/ftp\.(mozilla\.org.*)/,
    'http://archive.$1'
  ], [
    //Remove universal parameters
    /(?:(\?)|&)(?:(?:(?:utm_\w+|ref|soc_\w+|cc_key|PHPSESSID|ig_mid|igshid|__twitter_impression|ved|cmpid|newreg|tag|fbclid|fref|variation|searchVariation|tracking_id)=).*?)(?=&|$|#)/g,
    '$1'
  ], [
    //Remove unnecesary ? and &
    /(?:(\?)(?:&+(?!$|&)))|(?:&(?=&))|(?:(?:\??&+|\?)$)/g,
    '$1'
  ]],

  internalRules: {
    [Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST]: [
      // bypass blocked embed youtube videos
      [/^https:\/\/www\.youtube\.com\/get_video_info\?(?:video_id=(.+?)(?:&|%26)|.+?&video_id=(.+?)&).+?eurl=.+?(&.*|)$/,
       'https://www.youtube.com/get_video_info?video_id=$1$2&eurl=https%3A%2F%2Fyoutube.com$3'],
    ],
  },

  getRedirectUrl: function (originUrl, aRules = this.rules) {
    var nsIOriginUrl = Services.io.newURI(originUrl);
    if (nsIOriginUrl.scheme == 'jar' || !nsIOriginUrl.asciiHost)
      return false;
    try {
      var tld = Services.eTLD.getPublicSuffix(nsIOriginUrl).replace(/\./, '\\.');
    } catch (e) { // ip
      var tld = 'tld';
    }
    var redirectUrl = false;
    aRules?.forEach((rule) => {
      var regex = rule[3] ? new RegExp(rule[0].source.replace(/\.tld/, '\.' + tld)) : rule[0];
      if (regex.test(originUrl)) {
        if (!redirectUrl)
          redirectUrl = true;
        originUrl = typeof rule[1] == 'function'
          ? rule[2]
            ? decodeURIComponent(rule[1](originUrl.match(regex)))
            : rule[1](originUrl.match(regex))
          : rule[2]
            ? decodeURIComponent(originUrl.replace(regex, rule[1]))
            : originUrl.replace(regex, rule[1]);
      }
    });
    return redirectUrl ? originUrl : false;
  },

  get processScript () {
    return 'data:application/javascript;charset=UTF-8,(' + encodeURIComponent(function (rules, getRedirectUrl) {
      Components.utils.import("resource://gre/modules/Services.jsm");

      var {
        interfaces: Ci,
        results: Cr,
        manager: Cm
      } = Components;

      this.policy = {
        contractID: '@xiao/redirector;1',
        classID: Components.ID('{009e4d80-b13f-11e7-8f1a-0800200c9a66}'),
        xpcom_categories: ['content-policy', 'net-channel-event-sinks'],

        init: function () {
          Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(this.classID, 'Redirector', this.contractID, this);
          for (let category of this.xpcom_categories)
            Services.catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true);
        },

        destroy: function () {
          Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(this.classID, this);
          for (let category of this.xpcom_categories)
            Services.catMan.deleteCategoryEntry(category, this.contractID, false);
        },

        // nsIContentPolicy interface implementation
        shouldLoad: function (contentLocation, loadInfo) {
          if (loadInfo.externalContentPolicyType != Ci.nsIContentPolicy.TYPE_DOCUMENT)
            return Ci.nsIContentPolicy.ACCEPT;
          let redirectUrl = this.getRedirectUrl(contentLocation.spec);
          let node = loadInfo.loadingContext;
          if (redirectUrl && node) {
            node.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIBrowserChild).messageManager.sendAsyncMessage('Redirector', [redirectUrl, loadInfo.loadingPrincipal?.URI]);
            return Ci.nsIContentPolicy.REJECT_REQUEST;
          }
          return Ci.nsIContentPolicy.ACCEPT;
        },

        // nsIChannelEventSink interface implementation
        asyncOnChannelRedirect: function (oldChannel, newChannel, flags, redirectCallback) {
          this.onChannelRedirect(oldChannel, newChannel, flags);
          redirectCallback.onRedirectVerifyCallback(Cr.NS_OK);
        },

        onChannelRedirect: function (oldChannel, newChannel, flags) {
          if (!(newChannel.loadFlags & Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI))
            return;
          let newLocation = newChannel.URI.spec;
          if (!newLocation)
            return;
          let callbacks = [];
          if (newChannel.notificationCallbacks)
            callbacks.push(newChannel.notificationCallbacks);
          if (newChannel.loadGroup && newChannel.loadGroup.notificationCallbacks)
            callbacks.push(newChannel.loadGroup.notificationCallbacks);
          let webNav;
          for (let callback of callbacks) {
            try {
              webNav = callback.getInterface(Ci.nsILoadContext).topFrameElement.webNavigation;
              break;
            } catch(e) {}
          }
          if (!webNav)
            return;
          let redirectUrl = this.getRedirectUrl(newLocation);
          if (redirectUrl)
            webNav.loadURI(redirectUrl, {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});
        },

        createInstance: function (outer, iid) {
          if (outer)
            throw Cr.NS_ERROR_NO_AGGREGATION;
          return this.QueryInterface(iid);
        },

        QueryInterface: ChromeUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIChannelEventSink]),

        rules: rules,

        getRedirectUrl: getRedirectUrl
      };

      policy.init();
    }.toString() + ')(' + this.rules.toSource() + ', ' + this.getRedirectUrl.toString() + ')');
  },

  chromeListener: function (m) {
    m.target.loadURI(m.data[0], {referer: m.data[1], triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});
  },

  observe: function (subject) {
    let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
    let contentType = httpChannel.loadInfo.externalContentPolicyType;
    if (contentType != Ci.nsIContentPolicy.TYPE_DOCUMENT && contentType in this.internalRules) {
      let redirectUrl = this.getRedirectUrl(httpChannel.URI.spec, this.internalRules[contentType]);
      if (redirectUrl) {
        httpChannel.redirectTo(Services.io.newURI(redirectUrl));
      }
    }
  },

  init: function () {
    Services.ppmm.loadProcessScript(this.processScript, true);
    Services.mm.addMessageListener('Redirector', this.chromeListener);
    Services.obs.addObserver(this, 'http-on-modify-request', false);
  },

  destroy: function () {
    Services.ppmm.loadProcessScript('data:application/javascript;charset=UTF-8,' + encodeURIComponent('('+(function () {
      this.policy.destroy();
      delete this.policy;
    }).toString() + ')();'), false);
    Services.ppmm.removeDelayedProcessScript(this.processScript);
    Services.mm.removeMessageListener('Redirector', this.chromeListener);
    Services.obs.removeObserver(this, 'http-on-modify-request', false);
    delete UC.Redirector;
  }
}

UC.Redirector.init();<commit_msg>Redirector fx79: nsIContentPolicy (shouldLoad) is back to chrome process for the first time in e10s world, but in fact we don't need it.<commit_after>// ==UserScript==
// @name            Redirector
// @author          xiaoxiaoflood
// @include         main
// @shutdown        UC.Redirector.destroy();
// @onlyonce
// ==/UserScript==

// inspired by: https://github.com/harv/userChromeJS/blob/master/redirector_ui.uc.js

UC.Redirector = {

  // [regex, replace, decode, tld]
  rules: [[
    /^https?:\/\/redir\.folha\.com\.br\/redir\/online\/.+?\*(.+)/,
    '$1',
    true
  ], [
    /^https?:\/\/www\.google\.tld\/url\?(?:.*&)?(?:url|q)=([^&#]+).*/,
    '$1',
    true,
    true
  ], [
    /^https?:\/\/www\.google\.tld\/imgres\?imgurl=([^&#]+).*/,
    '$1',
    true,
    true
  ], [
    /^https:\/\/outgoing\.prod\.mozaws\.net\/v1\/\w+\/(.+)/,
    '$1',
    true
  ], [
    /^https?:\/\/click\.uol\.com\.br\/\?(?:.*&)?u=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/(?:(?:m|new)\.)?vk\.com\/away\.php\?(?:.*&)?to=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/l\.instagram\.com\/\?(?:.*&)?u=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/www\.youtube\.com\/redirect\?(?:.*&)?q=([^&#]+).*/,
    '$1',
    true
  ], [
    /^https?:\/\/www\.reddit\.com\/u(?:(?:ser\/([^\/]+)\/?$)|\/(?:([^\/]+)\/?$|(.*)))/,
    function (url) {
      return 'https://www.reddit.com/user/' + (url[3] ? url[3] : (url[1] || url[2]) + '/overview/');
    }
  ], [
    /^https?:\/\/bugzil\.la\/(.*)/,
    function (url) {
      return 'https://bugzilla.mozilla.org/' + (url[1] ? 'show_bug.cgi?id=' + url[1] : '');
    }
  ], [
    /^https?:\/\/youtu\.be\/(.*)/,
    function (url) {
      return 'https://www.youtube.com/' + (url[1] ? 'watch?v=' + url[1] : '');
    }
  ], [
    /^https?:\/\/(userscripts\.org(?:\:8080|)|(?:www.|)webextender.net)\/(.*)/,
    'http://userscripts-mirror.org/$2'
  ], [
    /^http:\/\/ftp\.(mozilla\.org.*)/,
    'http://archive.$1'
  ], [
    //Remove universal parameters
    /(?:(\?)|&)(?:(?:(?:utm_\w+|ref|soc_\w+|cc_key|PHPSESSID|ig_mid|igshid|__twitter_impression|ved|cmpid|newreg|tag|fbclid|fref|variation|searchVariation|tracking_id|seller_id|partner_id|gclid)=).*?)(?=&|$|#)/g,
    '$1'
  ], [
    //Remove unnecesary ? and &
    /(?:(\?)(?:&+(?!$|&)))|(?:&(?=&))|(?:(?:\??&+|\?)$)/g,
    '$1'
  ]],

  internalRules: {
    [Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST]: [
      // bypass blocked embed youtube videos
      [/^https:\/\/www\.youtube\.com\/get_video_info\?(?:video_id=(.+?)(?:&|%26)|.+?&video_id=(.+?)&).+?eurl=.+?(&.*|)$/,
       'https://www.youtube.com/get_video_info?video_id=$1$2&eurl=https%3A%2F%2Fyoutube.com$3'],
    ],
  },

  getRedirectUrl: function (originUrl, aRules = this.rules) {
    var nsIOriginUrl = Services.io.newURI(originUrl);
    if (nsIOriginUrl.scheme == 'jar' || !nsIOriginUrl.asciiHost)
      return false;
    try {
      var tld = Services.eTLD.getPublicSuffix(nsIOriginUrl).replace(/\./, '\\.');
    } catch (e) { // ip
      var tld = 'tld';
    }
    var redirectUrl = false;
    aRules?.forEach((rule) => {
      var regex = rule[3] ? new RegExp(rule[0].source.replace(/\.tld/, '\.' + tld)) : rule[0];
      if (regex.test(originUrl)) {
        if (!redirectUrl)
          redirectUrl = true;
        originUrl = typeof rule[1] == 'function'
          ? rule[2]
            ? decodeURIComponent(rule[1](originUrl.match(regex)))
            : rule[1](originUrl.match(regex))
          : rule[2]
            ? decodeURIComponent(originUrl.replace(regex, rule[1]))
            : originUrl.replace(regex, rule[1]);
      }
    });
    return redirectUrl ? originUrl : false;
  },

  observe: function (subject) {
    let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
    let contentType = httpChannel.loadInfo.externalContentPolicyType;
    if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) {
      let redirectUrl = this.getRedirectUrl(httpChannel.URI.spec);
      if (redirectUrl) {
        let loadInfo = httpChannel.loadInfo;
        loadInfo.browsingContext.embedderElement.loadURI(redirectUrl, {referer: loadInfo.loadingPrincipal?.URI, triggeringPrincipal: loadInfo.triggeringPrincipal});
      }
    } else if (contentType in this.internalRules) {
      let redirectUrl = this.getRedirectUrl(httpChannel.URI.spec, this.internalRules[contentType]);
      if (redirectUrl) {
        httpChannel.redirectTo(Services.io.newURI(redirectUrl));
      }
    }
  },

  init: function () {
    Services.obs.addObserver(this, 'http-on-modify-request', false);
  },

  destroy: function () {
    Services.obs.removeObserver(this, 'http-on-modify-request', false);
    delete UC.Redirector;
  }
}

UC.Redirector.init();<|endoftext|>


<commit_before>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/17/12
 * Time: 4:10 PM
 * To change this template use File | Settings | File Templates.
 */

define([
    'modules/base',
    'modules/mvc',
    'controller/page/page.controller',
    'model/page.model'
], function definePage(Base, MVC, Controller, Model) {
    var Page = function Page(opts) {

        opts = this.base.define(opts, {}, true);

        var uuid = this.base.isDefined(opts.uuid) ?
            opts.uuid :
            this.base.lib.generator.UUID();

        this.widgets = {};
        this.widget = {};
        this.collector = {};
        this.maximized = {};

        var DEFAULTS = {
            uuid: uuid,
            counter: 0,
            order: 1,
            layout: {
                overlapping: true,
                emptySpaces: true
            },
            widget: {
                counter: 0,
                allowToAdd: true
            },
            html: {
                header: false,
                footer: false
            }
//            menu: {
//                capability: App.permissionManager.capabilities.page.menu,
//                items: {
//                    rename: {
//                        title: App.i18n("page.menu.rename"),
//                        separator: false,
//                        callback: 'rename',
//                        capability: App.permissionManager.capabilities.page.rename
//                    },
//                    destroy: {
//                        title: App.i18n("page.menu.destroy"),
//                        separator: true,
//                        callback: 'destroy',
//                        capability: App.permissionManager.capabilities.page.destroy
//                    }
//                }
//            }
        };

        // Configure page
        this.config = this.base.lib.hash.extendHash(opts, DEFAULTS);

        // Init MVC
        new MVC({
            scope: this,
            components: [Controller, Model]
        });

//        this.layout = this.model.setLayout();

//        this.createWidget = this.model.createWidget;
//        this.current = this.workspace.controller.getCurrentPage;
//
//        this.view.render();

        // Hide all pages instead of this
//        this.workspace.controller.showCurrentPage(this);

    };

    return Page.extend(Base);
});
<commit_msg>add page default config<commit_after>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/17/12
 * Time: 4:10 PM
 * To change this template use File | Settings | File Templates.
 */

define([
    'modules/base',
    'modules/mvc',
    'controller/page/page.controller',
    'model/page.model'
], function definePage(Base, MVC, Controller, Model) {
    var Page = function Page(opts) {

        opts = this.base.define(opts, {}, true);

        var uuid = this.base.isDefined(opts.uuid) ?
            opts.uuid :
            this.base.lib.generator.UUID();

        this.widgets = {};
        this.widget = {};
        this.collector = {};
        this.maximized = {};

        var DEFAULTS = {
            uuid: uuid,
            counter: 0,
            order: 1,
            default: false,
            layout: {
                overlapping: true,
                emptySpaces: true
            },
            widget: {
                counter: 0,
                allowToAdd: true
            },
            html: {
                header: false,
                footer: false
            }
//            menu: {
//                capability: App.permissionManager.capabilities.page.menu,
//                items: {
//                    rename: {
//                        title: App.i18n("page.menu.rename"),
//                        separator: false,
//                        callback: 'rename',
//                        capability: App.permissionManager.capabilities.page.rename
//                    },
//                    destroy: {
//                        title: App.i18n("page.menu.destroy"),
//                        separator: true,
//                        callback: 'destroy',
//                        capability: App.permissionManager.capabilities.page.destroy
//                    }
//                }
//            }
        };

        // Configure page
        this.config = this.base.lib.hash.extendHash(opts, DEFAULTS);

        // Init MVC
        new MVC({
            scope: this,
            components: [Controller, Model]
        });

//        this.layout = this.model.setLayout();

//        this.createWidget = this.model.createWidget;
//        this.current = this.workspace.controller.getCurrentPage;
//
//        this.view.render();

        // Hide all pages instead of this
//        this.workspace.controller.showCurrentPage(this);

    };

    return Page.extend(Base);
});
<|endoftext|>


<commit_before>/*!
 * viewport-units-buggyfill v0.4.2
 * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
 * @author: Rodney Rehm - http://rodneyrehm.de/en/
 */

(function (root, factory) {
  'use strict';
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like enviroments that support module.exports,
    // like Node.
    module.exports = factory();
  } else {
    // Browser globals (root is window)
    root.viewportUnitsBuggyfill = factory();
  }
}(this, function () {
  'use strict';
  /*global document, window, location, XMLHttpRequest, XDomainRequest*/

  var initialized = false;
  var options;
  var userAgent = window.navigator.userAgent;
  var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
  var forEach = [].forEach;
  var dimensions;
  var declarations;
  var styleNode;
  var isOldInternetExplorer = false;
  var isOperaMini = userAgent.indexOf('Opera Mini') > -1;
  var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(userAgent) && (function() {
    // viewport units work fine in mobile Safari on iOS 8+
    var versions = /Version\/(\d+)/.exec(window.navigator.userAgent)
    return versions.length > 1 && parseInt(versions[1]) < 8;
  })();
  var isBadStockAndroid = (function() {
    // Android stock browser test derived from
    // http://stackoverflow.com/questions/24926221/distinguish-android-chrome-from-stock-browser-stock-browsers-user-agent-contai
    var isAndroid = userAgent.indexOf(' Android ') > -1;
    if (!isAndroid) {
      return false;
    }

    var isStockAndroid = userAgent.indexOf('Version/') > -1;
    if (!isStockAndroid) {
      return false;
    }

    var versionNumber = parseFloat((userAgent.match('Android ([0-9.]+)') || [])[1]);
    // anything below 4.4 uses WebKit without *any* viewport support
    return versionNumber < 4.4;
  })();

  // Do not remove the following comment!
  // It is a conditional comment used to
  // identify old Internet Explorer versions

  /*@cc_on

  @if (@_jscript_version <= 10)
    isOldInternetExplorer = true;
  @end

  @*/

  function debounce(func, wait) {
    var timeout;
    return function() {
      var context = this;
      var args = arguments;
      var callback = function() {
        func.apply(context, args);
      };

      clearTimeout(timeout);
      timeout = setTimeout(callback, wait);
    };
  }

  // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
  function inIframe() {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }

  function initialize(initOptions) {
    if (initialized) {
      return;
    }

    if (initOptions === true) {
      initOptions = {
        force: true
      };
    }

    options = initOptions || {};
    options.isMobileSafari = isMobileSafari;
    options.isBadStockAndroid = isBadStockAndroid;

    if (!options.force && !isMobileSafari && !isOldInternetExplorer && !isBadStockAndroid && !isOperaMini && (!options.hacks || !options.hacks.required(options))) {
      // this buggyfill only applies to mobile safari, IE9-10 and the Stock Android Browser.
      return;
    }

    options.hacks && options.hacks.initialize(options);

    initialized = true;
    styleNode = document.createElement('style');
    styleNode.id = 'patched-viewport';
    document.head.appendChild(styleNode);

    // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
    // therefore download and inject them as <style> to circumvent SOP.
    importCrossOriginLinks(function() {
      var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
      // doing a full refresh rather than updateStyles because an orientationchange
      // could activate different stylesheets
      window.addEventListener('orientationchange', _refresh, true);
      // orientationchange might have happened while in a different window
      window.addEventListener('pageshow', _refresh, true);

      if (options.force || isOldInternetExplorer || inIframe()) {
        window.addEventListener('resize', _refresh, true);
        options._listeningToResize = true;
      }

      options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);

      refresh();
    });
  }

  function updateStyles() {
    styleNode.textContent = getReplacedViewportUnits();
  }

  function refresh() {
    if (!initialized) {
      return;
    }

    findProperties();

    // iOS Safari will report window.innerWidth and .innerHeight as 0 unless a timeout is used here.
    // TODO: figure out WHY innerWidth === 0
    setTimeout(function() {
      updateStyles();
    }, 1);
  }

  function findProperties() {
    declarations = [];
    forEach.call(document.styleSheets, function(sheet) {
      if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
        // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
        return;
      }

      if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
        // skip entire sheet because media attribute doesn't match
        return;
      }

      forEach.call(sheet.cssRules, findDeclarations);
    });

    return declarations;
  }

  function findDeclarations(rule) {
    if (rule.type === 7) {
      var value = rule.cssText;
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        // KeyframesRule does not have a CSS-PropertyName
        declarations.push([rule, null, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
      }

      return;
    }

    if (!rule.style) {
      if (!rule.cssRules) {
        return;
      }

      forEach.call(rule.cssRules, function(_rule) {
        findDeclarations(_rule);
      });

      return;
    }

    forEach.call(rule.style, function(name) {
      var value = rule.style.getPropertyValue(name);
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        declarations.push([rule, name, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
      }
    });
  }

  function getReplacedViewportUnits() {
    dimensions = getViewport();

    var css = [];
    var buffer = [];
    var open;
    var close;

    declarations.forEach(function(item) {
      var _item = overwriteDeclaration.apply(null, item);
      var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
      var _close = new Array(_item.selector.length + 1).join('\n}');

      if (!_open || _open !== open) {
        if (buffer.length) {
          css.push(open + buffer.join('\n') + close);
          buffer.length = 0;
        }

        if (_open) {
          open = _open;
          close = _close;
          buffer.push(_item.content);
        } else {
          css.push(_item.content);
          open = null;
          close = null;
        }

        return;
      }

      if (_open && !open) {
        open = _open;
        close = _close;
      }

      buffer.push(_item.content);
    });

    if (buffer.length) {
      css.push(open + buffer.join('\n') + close);
    }

    // Opera Mini messes up on the content hack (it replaces the DOM node's innerHTML with the value).
    // This fixes it. We test for Opera Mini only since it is the most expensive CSS selector
    // see https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors
    if (isOperaMini) {
      css.push('* { content: normal !important; }');
    }

    return css.join('\n\n');
  }

  function overwriteDeclaration(rule, name, value) {
    var _value;
    var _selectors = [];

    _value = value.replace(viewportUnitExpression, replaceValues);

    if (options.hacks) {
      _value = options.hacks.overwriteDeclaration(rule, name, _value);
    }

    if (name) {
      // skipping KeyframesRule
      _selectors.push(rule.selectorText);
      _value = name + ': ' + _value + ';';
    }

    var _rule = rule.parentRule;
    while (_rule) {
      _selectors.unshift('@media ' + _rule.media.mediaText);
      _rule = _rule.parentRule;
    }

    return {
      selector: _selectors,
      content: _value
    };
  }

  function replaceValues(match, number, unit) {
    var _base = dimensions[unit];
    var _number = parseFloat(number) / 100;
    return (_number * _base) + 'px';
  }

  function getViewport() {
    var vh = window.innerHeight;
    var vw = window.innerWidth;

    return {
      vh: vh,
      vw: vw,
      vmax: Math.max(vw, vh),
      vmin: Math.min(vw, vh)
    };
  }

  function importCrossOriginLinks(next) {
    var _waiting = 0;
    var decrease = function() {
      _waiting--;
      if (!_waiting) {
        next();
      }
    };

    forEach.call(document.styleSheets, function(sheet) {
      if (!sheet.href || origin(sheet.href) === origin(location.href)) {
        // skip <style> and <link> from same origin
        return;
      }

      _waiting++;
      convertLinkToStyle(sheet.ownerNode, decrease);
    });

    if (!_waiting) {
      next();
    }
  }

  function origin(url) {
    return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
  }

  function convertLinkToStyle(link, next) {
    getCors(link.href, function() {
      var style = document.createElement('style');
      style.media = link.media;
      style.setAttribute('data-href', link.href);
      style.textContent = this.responseText;
      link.parentNode.replaceChild(style, link);
      next();
    }, next);
  }

  function getCors(url, success, error) {
    var xhr = new XMLHttpRequest();
    if ('withCredentials' in xhr) {
      // XHR for Chrome/Firefox/Opera/Safari.
      xhr.open('GET', url, true);
    } else if (typeof XDomainRequest !== 'undefined') {
      // XDomainRequest for IE.
      xhr = new XDomainRequest();
      xhr.open('GET', url);
    } else {
      throw new Error('cross-domain XHR not supported');
    }

    xhr.onload = success;
    xhr.onerror = error;
    xhr.send();
    return xhr;
  }

  return {
    version: '0.4.2',
    findProperties: findProperties,
    getCss: getReplacedViewportUnits,
    init: initialize,
    refresh: refresh
  };

}));
<commit_msg>fixing ASB UA-sniff<commit_after>/*!
 * viewport-units-buggyfill v0.4.2
 * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
 * @author: Rodney Rehm - http://rodneyrehm.de/en/
 */

(function (root, factory) {
  'use strict';
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like enviroments that support module.exports,
    // like Node.
    module.exports = factory();
  } else {
    // Browser globals (root is window)
    root.viewportUnitsBuggyfill = factory();
  }
}(this, function () {
  'use strict';
  /*global document, window, location, XMLHttpRequest, XDomainRequest*/

  var initialized = false;
  var options;
  var userAgent = window.navigator.userAgent;
  var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
  var forEach = [].forEach;
  var dimensions;
  var declarations;
  var styleNode;
  var isOldInternetExplorer = false;
  var isOperaMini = userAgent.indexOf('Opera Mini') > -1;
  var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(userAgent) && (function() {
    // viewport units work fine in mobile Safari on iOS 8+
    var versions = /Version\/(\d+)/.exec(window.navigator.userAgent)
    return versions.length > 1 && parseInt(versions[1]) < 8;
  })();
  var isBadStockAndroid = (function() {
    // Android stock browser test derived from
    // http://stackoverflow.com/questions/24926221/distinguish-android-chrome-from-stock-browser-stock-browsers-user-agent-contai
    var isAndroid = userAgent.indexOf(' Android ') > -1;
    if (!isAndroid) {
      return false;
    }

    var isStockAndroid = userAgent.indexOf('Version/') > -1;
    if (!isStockAndroid) {
      return false;
    }

    var versionNumber = parseFloat((userAgent.match('Android ([0-9.]+)') || [])[1]);
    // anything below 4.4 uses WebKit without *any* viewport support,
    // 4.4 has issues with viewport units within calc()
    return versionNumber <= 4.4;
  })();

  // Do not remove the following comment!
  // It is a conditional comment used to
  // identify old Internet Explorer versions

  /*@cc_on

  @if (@_jscript_version <= 10)
    isOldInternetExplorer = true;
  @end

  @*/

  function debounce(func, wait) {
    var timeout;
    return function() {
      var context = this;
      var args = arguments;
      var callback = function() {
        func.apply(context, args);
      };

      clearTimeout(timeout);
      timeout = setTimeout(callback, wait);
    };
  }

  // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
  function inIframe() {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }

  function initialize(initOptions) {
    if (initialized) {
      return;
    }

    if (initOptions === true) {
      initOptions = {
        force: true
      };
    }

    options = initOptions || {};
    options.isMobileSafari = isMobileSafari;
    options.isBadStockAndroid = isBadStockAndroid;

    if (!options.force && !isMobileSafari && !isOldInternetExplorer && !isBadStockAndroid && !isOperaMini && (!options.hacks || !options.hacks.required(options))) {
      // this buggyfill only applies to mobile safari, IE9-10 and the Stock Android Browser.
      return;
    }

    options.hacks && options.hacks.initialize(options);

    initialized = true;
    styleNode = document.createElement('style');
    styleNode.id = 'patched-viewport';
    document.head.appendChild(styleNode);

    // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
    // therefore download and inject them as <style> to circumvent SOP.
    importCrossOriginLinks(function() {
      var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
      // doing a full refresh rather than updateStyles because an orientationchange
      // could activate different stylesheets
      window.addEventListener('orientationchange', _refresh, true);
      // orientationchange might have happened while in a different window
      window.addEventListener('pageshow', _refresh, true);

      if (options.force || isOldInternetExplorer || inIframe()) {
        window.addEventListener('resize', _refresh, true);
        options._listeningToResize = true;
      }

      options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);

      refresh();
    });
  }

  function updateStyles() {
    styleNode.textContent = getReplacedViewportUnits();
  }

  function refresh() {
    if (!initialized) {
      return;
    }

    findProperties();

    // iOS Safari will report window.innerWidth and .innerHeight as 0 unless a timeout is used here.
    // TODO: figure out WHY innerWidth === 0
    setTimeout(function() {
      updateStyles();
    }, 1);
  }

  function findProperties() {
    declarations = [];
    forEach.call(document.styleSheets, function(sheet) {
      if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
        // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
        return;
      }

      if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
        // skip entire sheet because media attribute doesn't match
        return;
      }

      forEach.call(sheet.cssRules, findDeclarations);
    });

    return declarations;
  }

  function findDeclarations(rule) {
    if (rule.type === 7) {
      var value = rule.cssText;
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        // KeyframesRule does not have a CSS-PropertyName
        declarations.push([rule, null, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
      }

      return;
    }

    if (!rule.style) {
      if (!rule.cssRules) {
        return;
      }

      forEach.call(rule.cssRules, function(_rule) {
        findDeclarations(_rule);
      });

      return;
    }

    forEach.call(rule.style, function(name) {
      var value = rule.style.getPropertyValue(name);
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        declarations.push([rule, name, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
      }
    });
  }

  function getReplacedViewportUnits() {
    dimensions = getViewport();

    var css = [];
    var buffer = [];
    var open;
    var close;

    declarations.forEach(function(item) {
      var _item = overwriteDeclaration.apply(null, item);
      var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
      var _close = new Array(_item.selector.length + 1).join('\n}');

      if (!_open || _open !== open) {
        if (buffer.length) {
          css.push(open + buffer.join('\n') + close);
          buffer.length = 0;
        }

        if (_open) {
          open = _open;
          close = _close;
          buffer.push(_item.content);
        } else {
          css.push(_item.content);
          open = null;
          close = null;
        }

        return;
      }

      if (_open && !open) {
        open = _open;
        close = _close;
      }

      buffer.push(_item.content);
    });

    if (buffer.length) {
      css.push(open + buffer.join('\n') + close);
    }

    // Opera Mini messes up on the content hack (it replaces the DOM node's innerHTML with the value).
    // This fixes it. We test for Opera Mini only since it is the most expensive CSS selector
    // see https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors
    if (isOperaMini) {
      css.push('* { content: normal !important; }');
    }

    return css.join('\n\n');
  }

  function overwriteDeclaration(rule, name, value) {
    var _value;
    var _selectors = [];

    _value = value.replace(viewportUnitExpression, replaceValues);

    if (options.hacks) {
      _value = options.hacks.overwriteDeclaration(rule, name, _value);
    }

    if (name) {
      // skipping KeyframesRule
      _selectors.push(rule.selectorText);
      _value = name + ': ' + _value + ';';
    }

    var _rule = rule.parentRule;
    while (_rule) {
      _selectors.unshift('@media ' + _rule.media.mediaText);
      _rule = _rule.parentRule;
    }

    return {
      selector: _selectors,
      content: _value
    };
  }

  function replaceValues(match, number, unit) {
    var _base = dimensions[unit];
    var _number = parseFloat(number) / 100;
    return (_number * _base) + 'px';
  }

  function getViewport() {
    var vh = window.innerHeight;
    var vw = window.innerWidth;

    return {
      vh: vh,
      vw: vw,
      vmax: Math.max(vw, vh),
      vmin: Math.min(vw, vh)
    };
  }

  function importCrossOriginLinks(next) {
    var _waiting = 0;
    var decrease = function() {
      _waiting--;
      if (!_waiting) {
        next();
      }
    };

    forEach.call(document.styleSheets, function(sheet) {
      if (!sheet.href || origin(sheet.href) === origin(location.href)) {
        // skip <style> and <link> from same origin
        return;
      }

      _waiting++;
      convertLinkToStyle(sheet.ownerNode, decrease);
    });

    if (!_waiting) {
      next();
    }
  }

  function origin(url) {
    return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
  }

  function convertLinkToStyle(link, next) {
    getCors(link.href, function() {
      var style = document.createElement('style');
      style.media = link.media;
      style.setAttribute('data-href', link.href);
      style.textContent = this.responseText;
      link.parentNode.replaceChild(style, link);
      next();
    }, next);
  }

  function getCors(url, success, error) {
    var xhr = new XMLHttpRequest();
    if ('withCredentials' in xhr) {
      // XHR for Chrome/Firefox/Opera/Safari.
      xhr.open('GET', url, true);
    } else if (typeof XDomainRequest !== 'undefined') {
      // XDomainRequest for IE.
      xhr = new XDomainRequest();
      xhr.open('GET', url);
    } else {
      throw new Error('cross-domain XHR not supported');
    }

    xhr.onload = success;
    xhr.onerror = error;
    xhr.send();
    return xhr;
  }

  return {
    version: '0.4.2',
    findProperties: findProperties,
    getCss: getReplacedViewportUnits,
    init: initialize,
    refresh: refresh
  };

}));
<|endoftext|>