Fix #548
[KisSync.git] / src / utilities.js
blobb7f191d120690673ce0ae366a31e97d0f6e4ed19
1 (function () {
2 var root, crypto, net = false;
4 if (typeof window === "undefined") {
5 root = module.exports;
6 } else {
7 root = window.utils = {};
10 if (typeof require === "function") {
11 crypto = require("crypto");
12 net = require("net");
15 var Set = function (items) {
16 this._items = {};
17 var self = this;
18 if (items instanceof Array)
19 items.forEach(function (it) { self.add(it); });
22 Set.prototype.contains = function (what) {
23 return (what in this._items);
26 Set.prototype.add = function (what) {
27 this._items[what] = true;
30 Set.prototype.remove = function (what) {
31 if (what in this._items)
32 delete this._items[what];
35 Set.prototype.clear = function () {
36 this._items = {};
39 Set.prototype.forEach = function (fn) {
40 for (var k in this._items) {
41 fn(k);
45 root.Set = Set;
47 root.isValidChannelName = function (name) {
48 return name.match(/^[\w-]{1,30}$/);
51 root.isValidUserName = function (name) {
52 return name.match(/^[\w-]{1,20}$/);
55 root.isValidEmail = function (email) {
56 if (email.length > 255) {
57 return false;
60 if (!email.match(/^[^@]+?@[^@]+$/)) {
61 return false;
64 if (email.match(/^[^@]+?@(localhost|127\.0\.0\.1)$/)) {
65 return false;
68 return true;
71 root.randomSalt = function (length) {
72 var chars = "abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
73 + "0123456789!@#$%^&*_+=~";
74 var salt = [];
75 for(var i = 0; i < length; i++) {
76 salt.push(chars[parseInt(Math.random()*chars.length)]);
78 return salt.join('');
81 root.getIPRange = function (ip) {
82 if (net.isIPv6(ip)) {
83 return root.expandIPv6(ip)
84 .replace(/((?:[0-9a-f]{4}:){3}[0-9a-f]{4}):(?:[0-9a-f]{4}:){3}[0-9a-f]{4}/, "$1");
85 } else {
86 return ip.replace(/((?:[0-9]+\.){2}[0-9]+)\.[0-9]+/, "$1");
90 root.getWideIPRange = function (ip) {
91 if (net.isIPv6(ip)) {
92 return root.expandIPv6(ip)
93 .replace(/((?:[0-9a-f]{4}:){2}[0-9a-f]{4}):(?:[0-9a-f]{4}:){4}[0-9a-f]{4}/, "$1");
94 } else {
95 return ip.replace(/([0-9]+\.[0-9]+)\.[0-9]+\.[0-9]+/, "$1");
99 root.expandIPv6 = function (ip) {
100 var result = "0000:0000:0000:0000:0000:0000:0000:0000".split(":");
101 var parts = ip.split("::");
102 var left = parts[0].split(":");
103 var i = 0;
104 left.forEach(function (block) {
105 while (block.length < 4) {
106 block = "0" + block;
108 result[i++] = block;
111 if (parts.length > 1) {
112 var right = parts[1].split(":");
113 i = 7;
114 right.forEach(function (block) {
115 while (block.length < 4) {
116 block = "0" + block;
118 result[i--] = block;
122 return result.join(":");
125 root.formatTime = function (sec) {
126 if(sec === "--:--")
127 return sec;
129 sec = Math.floor(+sec);
130 var h = "", m = "", s = "";
132 if(sec >= 3600) {
133 h = "" + Math.floor(sec / 3600);
134 if(h.length < 2)
135 h = "0" + h;
136 sec %= 3600;
139 m = "" + Math.floor(sec / 60);
140 if(m.length < 2)
141 m = "0" + m;
143 s = "" + (sec % 60);
144 if(s.length < 2)
145 s = "0" + s;
147 if(h === "")
148 return [m, s].join(":");
150 return [h, m, s].join(":");
153 root.parseTime = function (time) {
154 var parts = time.split(":").reverse();
155 var seconds = 0;
156 switch (parts.length) {
157 case 3:
158 seconds += parseInt(parts[2]) * 3600;
159 case 2:
160 seconds += parseInt(parts[1]) * 60;
161 case 1:
162 seconds += parseInt(parts[0]);
163 break;
164 default:
165 break;
167 return seconds;
170 root.newRateLimiter = function () {
171 return {
172 count: 0,
173 lastTime: 0,
174 throttle: function (opts) {
175 if (typeof opts === "undefined")
176 opts = {};
178 var burst = +opts.burst,
179 sustained = +opts.sustained,
180 cooldown = +opts.cooldown;
182 if (isNaN(burst))
183 burst = 10;
185 if (isNaN(sustained))
186 sustained = 2;
188 if (isNaN(cooldown))
189 cooldown = burst / sustained;
191 // Cooled down, allow and clear buffer
192 if (this.lastTime < Date.now() - cooldown*1000) {
193 this.count = 1;
194 this.lastTime = Date.now();
195 return false;
198 // Haven't reached burst cap yet, allow
199 if (this.count < burst) {
200 this.count++;
201 this.lastTime = Date.now();
202 return false;
205 var diff = Date.now() - this.lastTime;
206 if (diff < 1000/sustained)
207 return true;
209 this.lastTime = Date.now();
210 return false;
215 root.formatLink = function (id, type) {
216 switch (type) {
217 case "yt":
218 return "http://youtu.be/" + id;
219 case "vi":
220 return "http://vimeo.com/" + id;
221 case "dm":
222 return "http://dailymotion.com/video/" + id;
223 case "sc":
224 return id;
225 case "li":
226 return "http://livestream.com/" + id;
227 case "tw":
228 return "http://twitch.tv/" + id;
229 case "rt":
230 return id;
231 case "jw":
232 return id;
233 case "im":
234 return "http://imgur.com/a/" + id;
235 case "us":
236 return "http://ustream.tv/" + id;
237 case "gd":
238 return "https://docs.google.com/file/d/" + id;
239 case "fi":
240 return id;
241 case "hb":
242 return "http://hitbox.tv/" + id;
243 default:
244 return "";
248 root.isLive = function (type) {
249 switch (type) {
250 case "li":
251 case "tw":
252 case "us":
253 case "rt":
254 case "cu":
255 case "im":
256 case "jw":
257 case "hb":
258 return true;
259 default:
260 return false;
264 root.sha1 = function (data) {
265 if (!crypto) {
266 return "";
268 var shasum = crypto.createHash("sha1");
269 shasum.update(data);
270 return shasum.digest("hex");
273 root.cloakIP = function (ip) {
274 if (ip.match(/\d+\.\d+(\.\d+)?(\.\d+)?/)) {
275 return cloakIPv4(ip);
276 } else if (ip.match(/([0-9a-f]{1,4}\:){1,7}[0-9a-f]{1,4}/)) {
277 return cloakIPv6(ip);
278 } else {
279 return ip;
282 function iphash(data, len) {
283 var md5 = crypto.createHash("md5");
284 md5.update(data);
285 return md5.digest("base64").substring(0, len);
288 function cloakIPv4(ip) {
289 var parts = ip.split(".");
290 var accumulator = "";
292 parts = parts.map(function (segment, i) {
293 if (i < 2) return segment;
295 var part = iphash(accumulator + segment + i, 3);
296 accumulator += segment;
297 return part;
300 while (parts.length < 4) parts.push("*");
301 return parts.join(".");
304 function cloakIPv6(ip) {
305 var parts = ip.split(":");
306 parts.splice(4, 4);
307 var accumulator = "";
309 parts = parts.map(function (segment, i) {
310 if (i < 2) return segment;
312 var part = iphash(accumulator + segment + i, 4);
313 accumulator += segment;
314 return part;
317 while (parts.length < 4) parts.push("*");
318 return parts.join(":");
321 })();