| 113 | | |
|---|
| 114 | | function merge(me, that) { |
|---|
| 115 | | for (let c in that) { |
|---|
| 116 | | me[c] = that[c]; |
|---|
| 117 | | } |
|---|
| 118 | | } |
|---|
| 119 | | |
|---|
| 120 | | // not instanceof save, you know ;) |
|---|
| 121 | | function clone(obj) { |
|---|
| 122 | | var rv = {}; |
|---|
| 123 | | merge(rv, obj); |
|---|
| 124 | | merge(rv.prototype, this.prototype); |
|---|
| 125 | | rv.constructor = this.constructor; |
|---|
| 126 | | return rv; |
|---|
| 127 | | } |
|---|
| 128 | | merge( |
|---|
| 129 | | String.prototype, |
|---|
| 130 | | { |
|---|
| 131 | | trim: function() { |
|---|
| 132 | | return this.replace(/^\s+|\s+$/g, ''); |
|---|
| 133 | | }, |
|---|
| 134 | | removeBadChars: function() { |
|---|
| 135 | | return this |
|---|
| 136 | | .replace(/[\n\r\v?:<>*|"]/g, '_') |
|---|
| 137 | | .replace(/%(?:25)?20/g, ' '); |
|---|
| 138 | | }, |
|---|
| 139 | | addFinalSlash: function() { |
|---|
| 140 | | if (this.length == 0) { |
|---|
| 141 | | return SYSTEMSLASH; |
|---|
| 142 | | } |
|---|
| 143 | | |
|---|
| 144 | | if (this[this.length - 1] != SYSTEMSLASH) { |
|---|
| 145 | | return this + SYSTEMSLASH; |
|---|
| 146 | | } |
|---|
| 147 | | return this; |
|---|
| 148 | | }, |
|---|
| 149 | | removeFinalChar: function(c) { |
|---|
| 150 | | if (this.length == 0) { |
|---|
| 151 | | return this; |
|---|
| 152 | | } |
|---|
| 153 | | if (this[this.length - 1] == c) { |
|---|
| 154 | | return this.substring(0, this.length - 1); |
|---|
| 155 | | } |
|---|
| 156 | | return this; |
|---|
| 157 | | }, |
|---|
| 158 | | removeLeadingChar: function(c) { |
|---|
| 159 | | if (this.length == 0) { |
|---|
| 160 | | return this; |
|---|
| 161 | | } |
|---|
| 162 | | if (this[0] == c) { |
|---|
| 163 | | return this.slice(1); |
|---|
| 164 | | } |
|---|
| 165 | | return this; |
|---|
| 166 | | }, |
|---|
| 167 | | removeFinalSlash: function() { |
|---|
| 168 | | return this.removeFinalChar(SYSTEMSLASH); |
|---|
| 169 | | }, |
|---|
| 170 | | replaceSlashes: function(replaceWith) { |
|---|
| 171 | | return this.replace(/[\\/]/g, replaceWith); |
|---|
| 172 | | }, |
|---|
| 173 | | normalizeSlashes: function() { |
|---|
| 174 | | return this.replaceSlashes(SYSTEMSLASH); |
|---|
| 175 | | }, |
|---|
| 176 | | removeLeadingSlash: function() { |
|---|
| 177 | | return this.removeLeadingChar(SYSTEMSLASH); |
|---|
| 178 | | }, |
|---|
| 179 | | getUsableFileName: function() { |
|---|
| 180 | | let t = this.replace(/\?.*$/, '') |
|---|
| 181 | | .normalizeSlashes() |
|---|
| 182 | | .trim() |
|---|
| 183 | | .removeFinalSlash(); |
|---|
| 184 | | return t.split(SYSTEMSLASH).pop().removeBadChars().trim(); |
|---|
| 185 | | }, |
|---|
| 186 | | getExtension: function() { |
|---|
| 187 | | let name = this.getUsableFileName(); |
|---|
| 188 | | let c = name.lastIndexOf('.'); |
|---|
| 189 | | if (c == -1) { |
|---|
| 190 | | return null; |
|---|
| 191 | | } |
|---|
| 192 | | return name.slice(c + 1); |
|---|
| 193 | | }, |
|---|
| 194 | | cropCenter : function(newLength) { |
|---|
| 195 | | if (this.length > newLength) { |
|---|
| 196 | | return this.substring(0, newLength / 2) + "..." + this.substring(this.length - newLength / 2, this.length); |
|---|
| 197 | | } |
|---|
| 198 | | return this; |
|---|
| 199 | | }, |
|---|
| 200 | | toURI: function(charset, baseURI) { |
|---|
| 201 | | return IOService.newURI(this, charset, baseURI); |
|---|
| 202 | | }, |
|---|
| 203 | | toURL: function(charset, baseURI) { |
|---|
| 204 | | return this.toURI(charset, baseURI).QueryInterface(Components.interfaces.nsIURL); |
|---|
| 205 | | } |
|---|
| 206 | | } |
|---|
| 207 | | ); |
|---|
| 348 | | |
|---|
| 349 | | /** |
|---|
| 350 | | * returns a pretty number containing at least specified number of digits |
|---|
| 351 | | * @param aNumber the number to format |
|---|
| 352 | | * @param aDigists Optional. Number of digits the result must at least have |
|---|
| 353 | | * @author Nils |
|---|
| 354 | | */ |
|---|
| 355 | | formatNumber: function U_formatNumber(rv, digits) { |
|---|
| 356 | | rv = _atos(rv); |
|---|
| 357 | | if (typeof(digits) != 'number') { |
|---|
| 358 | | digits = 3; |
|---|
| 359 | | } |
|---|
| 360 | | while (rv.length < digits) { |
|---|
| 361 | | rv = '0' + rv; |
|---|
| 362 | | } |
|---|
| 363 | | return rv; |
|---|
| 364 | | }, |
|---|
| 365 | | /** |
|---|
| 366 | | * formats a time-delta. At least minutes and seconds are given back |
|---|
| 367 | | */ |
|---|
| 368 | | formatTimeDelta: function U_formatTimeDelta(aDelta) { |
|---|
| 369 | | var h = Math.floor(aDelta / 3600); |
|---|
| 370 | | var m = Math.floor((aDelta % 3600) / 60); |
|---|
| 371 | | var s = Math.floor(aDelta % 60); |
|---|
| 372 | | if (h) { |
|---|
| 373 | | return this.formatNumber(h, 2) + ":" + this.formatNumber(m, 2) + ":" + this.formatNumber(s, 2); |
|---|
| 374 | | } |
|---|
| 375 | | return this.formatNumber(m, 2) + ":" + this.formatNumber(s, 2); |
|---|
| 376 | | }, |
|---|
| 377 | | |
|---|
| | 221 | |
|---|
| | 222 | |
|---|
| 391 | | function _getIcon(url, size) { |
|---|
| 392 | | if (/mac/i.test(navigator.platform)) { |
|---|
| 393 | | const _recognizedMac = /\.(?:gz|zip|gif|jpe?g|jpe|mp3|pdf|avi|mpe?g)$/i; |
|---|
| 394 | | _getIcon = function _getIconMac(url, size) { |
|---|
| 395 | | let uri = url.toURI(); |
|---|
| 396 | | if (_recognizedMac.test(uri.path)) { |
|---|
| 397 | | return "moz-icon://" + url + "?size=" + size; |
|---|
| 398 | | } |
|---|
| 399 | | return "moz-icon://file.html?size=" + size; |
|---|
| 400 | | }; |
|---|
| 401 | | } |
|---|
| 402 | | else { |
|---|
| 403 | | _getIcon = function _getIconOther(url, size) { |
|---|
| 404 | | return "moz-icon://" + url + "?size=" + size; |
|---|
| 405 | | }; |
|---|
| 406 | | } |
|---|
| 407 | | return _getIcon(url, size); |
|---|
| 408 | | }; |
|---|
| | 236 | Components.utils.import('resource://dta/utils.jsm', Utils); |
|---|
| | 237 | |
|---|
| | 238 | Utils.merge( |
|---|
| | 239 | String.prototype, |
|---|
| | 240 | { |
|---|
| | 241 | trim: function() { |
|---|
| | 242 | return this.replace(/^\s+|\s+$/g, ''); |
|---|
| | 243 | }, |
|---|
| | 244 | removeBadChars: function() { |
|---|
| | 245 | return this |
|---|
| | 246 | .replace(/[\n\r\v?:<>*|"]/g, '_') |
|---|
| | 247 | .replace(/%(?:25)?20/g, ' '); |
|---|
| | 248 | }, |
|---|
| | 249 | addFinalSlash: function() { |
|---|
| | 250 | if (this.length == 0) { |
|---|
| | 251 | return SYSTEMSLASH; |
|---|
| | 252 | } |
|---|
| | 253 | |
|---|
| | 254 | if (this[this.length - 1] != SYSTEMSLASH) { |
|---|
| | 255 | return this + SYSTEMSLASH; |
|---|
| | 256 | } |
|---|
| | 257 | return this; |
|---|
| | 258 | }, |
|---|
| | 259 | removeFinalChar: function(c) { |
|---|
| | 260 | if (this.length == 0) { |
|---|
| | 261 | return this; |
|---|
| | 262 | } |
|---|
| | 263 | if (this[this.length - 1] == c) { |
|---|
| | 264 | return this.substring(0, this.length - 1); |
|---|
| | 265 | } |
|---|
| | 266 | return this; |
|---|
| | 267 | }, |
|---|
| | 268 | removeLeadingChar: function(c) { |
|---|
| | 269 | if (this.length == 0) { |
|---|
| | 270 | return this; |
|---|
| | 271 | } |
|---|
| | 272 | if (this[0] == c) { |
|---|
| | 273 | return this.slice(1); |
|---|
| | 274 | } |
|---|
| | 275 | return this; |
|---|
| | 276 | }, |
|---|
| | 277 | removeFinalSlash: function() { |
|---|
| | 278 | return this.removeFinalChar(SYSTEMSLASH); |
|---|
| | 279 | }, |
|---|
| | 280 | replaceSlashes: function(replaceWith) { |
|---|
| | 281 | return this.replace(/[\\/]/g, replaceWith); |
|---|
| | 282 | }, |
|---|
| | 283 | normalizeSlashes: function() { |
|---|
| | 284 | return this.replaceSlashes(SYSTEMSLASH); |
|---|
| | 285 | }, |
|---|
| | 286 | removeLeadingSlash: function() { |
|---|
| | 287 | return this.removeLeadingChar(SYSTEMSLASH); |
|---|
| | 288 | }, |
|---|
| | 289 | getUsableFileName: function() { |
|---|
| | 290 | let t = this.replace(/\?.*$/, '') |
|---|
| | 291 | .normalizeSlashes() |
|---|
| | 292 | .trim() |
|---|
| | 293 | .removeFinalSlash(); |
|---|
| | 294 | return t.split(SYSTEMSLASH).pop().removeBadChars().trim(); |
|---|
| | 295 | }, |
|---|
| | 296 | getExtension: function() { |
|---|
| | 297 | let name = this.getUsableFileName(); |
|---|
| | 298 | let c = name.lastIndexOf('.'); |
|---|
| | 299 | return (c == - 1) ? null : name.slice(++c); |
|---|
| | 300 | }, |
|---|
| | 301 | cropCenter : function(newLength) { |
|---|
| | 302 | if (this.length > newLength) { |
|---|
| | 303 | return this.substring(0, newLength / 2) + "..." + this.substring(this.length - newLength / 2, this.length); |
|---|
| | 304 | } |
|---|
| | 305 | return this; |
|---|
| | 306 | }, |
|---|
| | 307 | toURI: function(charset, baseURI) { |
|---|
| | 308 | return IOService.newURI(this, charset, baseURI); |
|---|
| | 309 | }, |
|---|
| | 310 | toURL: function(charset, baseURI) { |
|---|
| | 311 | return this.toURI(charset, baseURI).QueryInterface(Components.interfaces.nsIURL); |
|---|
| | 312 | } |
|---|
| | 313 | } |
|---|
| | 314 | ); |
|---|
| | 315 | |
|---|
| | 327 | |
|---|
| | 328 | const _recognizedMac = /\.(?:gz|zip|gif|jpe?g|jpe|mp3|pdf|avi|mpe?g)$/i; |
|---|
| | 329 | |
|---|
| | 330 | function _getIconMac(url, size) { |
|---|
| | 331 | let uri = url.toURI(); |
|---|
| | 332 | if (_recognizedMac.test(uri.path)) { |
|---|
| | 333 | return "moz-icon://" + url + "?size=" + size; |
|---|
| | 334 | } |
|---|
| | 335 | return "moz-icon://file.html?size=" + size; |
|---|
| | 336 | } |
|---|
| | 337 | |
|---|
| | 338 | function _getIconOther(url, size) { |
|---|
| | 339 | return "moz-icon://" + url + "?size=" + size; |
|---|
| | 340 | }; |
|---|
| | 341 | |
|---|
| | 342 | function _getIcon(url, size) { |
|---|
| | 343 | if (/mac/i.test(navigator.platform)) { |
|---|
| | 344 | _getIcon = _getIconMac; |
|---|
| | 345 | } |
|---|
| | 346 | else { |
|---|
| | 347 | _getIcon = _getIconOther; |
|---|
| | 348 | } |
|---|
| | 349 | return _getIcon(url, size); |
|---|
| | 350 | }; |
|---|
| | 351 | |
|---|
| 571 | | /** |
|---|
| 572 | | * Range generator (python style). Difference: step direction is initialized accordingly if corresponding parameter is omitted. |
|---|
| 573 | | * @param start Optional. Start value (default: 0) |
|---|
| 574 | | * @param stop Stop value (exclusive) |
|---|
| 575 | | * @param step Optional. Step value (default: 1/-1) |
|---|
| 576 | | * @author Nils |
|---|
| 577 | | */ |
|---|
| 578 | | function range() { |
|---|
| 579 | | if (arguments.length == 0) { |
|---|
| 580 | | throw Components.results.NS_ERROR_INVALID_ARG; |
|---|
| 581 | | } |
|---|
| 582 | | var start = 0, stop = Number(arguments[0]), step; |
|---|
| 583 | | if (arguments.length >= 2) { |
|---|
| 584 | | start = stop; |
|---|
| 585 | | stop = Number(arguments[1]); |
|---|
| 586 | | } |
|---|
| 587 | | if (arguments.length >= 3) { |
|---|
| 588 | | step = Number(arguments[2]); |
|---|
| 589 | | } |
|---|
| 590 | | else { |
|---|
| 591 | | step = stop - start > 0 ? 1 : -1; |
|---|
| 592 | | } |
|---|
| 593 | | if (!isFinite(start) || !isFinite(stop) || !isFinite(step) || step == 0) { |
|---|
| 594 | | throw Components.results.NS_ERROR_INVALID_ARG; |
|---|
| 595 | | } |
|---|
| 596 | | if ((stop - start) / step < 0) { |
|---|
| 597 | | // negative range |
|---|
| 598 | | return; |
|---|
| 599 | | } |
|---|
| 600 | | stop += -Math.abs(step)/step; |
|---|
| 601 | | stop += step - ((stop - start) % step); |
|---|
| 602 | | for (; start != stop; start += step) { |
|---|
| 603 | | yield start; |
|---|
| 604 | | } |
|---|
| 605 | | |
|---|
| 606 | | } |
|---|
| 607 | | |
|---|
| 608 | | /** |
|---|
| 609 | | * Convert string-castable data int a hexdigest string |
|---|
| 610 | | * @param data String-castable data to hash |
|---|
| 611 | | * @return The hex digest of given data |
|---|
| 612 | | * @author Nils (derived from dmo example) |
|---|
| 613 | | */ |
|---|
| 614 | | function hexdigest(data) { |
|---|
| 615 | | data = _atos(data); |
|---|
| 616 | | // range is required as we extended String |
|---|
| 617 | | return [("0" + data.charCodeAt(i).toString(16)).slice(-2) for (i in range(data.length))].join(""); |
|---|
| 618 | | } |
|---|