diff --git a/.gitignore b/.gitignore index 6f28064..85f174b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,9 @@ node_modules .vscode data -npm-debug.log - *.swp *.swo -*.DS_Store \ No newline at end of file +*.DS_Store + +npm-debug.log +static/application.min.js \ No newline at end of file diff --git a/README.md b/README.md index 23ca077..87eb741 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ STDOUT. Check the README there for more details and usages. ## Tested Browsers -* Firefox 8 +* Firefox 81 * Chrome 17 * Safari 5.3 @@ -41,7 +41,7 @@ STDOUT. Check the README there for more details and usages. * `maxLength` - maximum length of a paste (default 400000) * `staticMaxAge` - max age for static assets (86400) * `recompressStaticAssets` - whether or not to compile static js assets (true) -* `documents` - static documents to serve (ex: http://hastebin.com/about.com) +* `documents` - static documents to serve (ex: http://hastebin.com/about.md) in addition to static assets. These will never expire. * `storage` - storage options (see below) * `logging` - logging preferences @@ -51,10 +51,10 @@ STDOUT. Check the README there for more details and usages. ## Rate Limiting When present, the `rateLimits` option enables built-in rate limiting courtesy -of `connect-ratelimit`. Any of the options supported by that library can be -used and set in `config.json`. +of `express-rate-limit`. Any of the options supported by that library can be +used and set in `config.js`. -See the README for [connect-ratelimit](https://github.com/dharmafly/connect-ratelimit) +See the README for [express-rate-limit](https://www.npmjs.com/package/express-rate-limit) for more information! ## Key Generation @@ -92,8 +92,8 @@ something like: ``` json { - "path": "./data", - "type": "file" + "type": "file", + "path": "./data" } ``` diff --git a/about.md b/about.md index c446934..992c303 100644 --- a/about.md +++ b/about.md @@ -53,9 +53,10 @@ pastes. Haste can easily be installed behind your network, and it's all open source! * [haste-client](https://github.com/seejohnrun/haste-client) -* [haste-server](https://github.com/seejohnrun/haste-server) +* [haste-server](https://github.com/zneix/haste-server) ## Author -Code by John Crepezzi +Original Code by John Crepezzi +Continued by zneix Key Design by Brian Dawson diff --git a/config.js b/config.js new file mode 100644 index 0000000..8d9f891 --- /dev/null +++ b/config.js @@ -0,0 +1,31 @@ +module.exports = { + "host": "127.0.0.1", + "port": 4200, + + "keyLength": 10, + "maxLength": 400000, + + "staticMaxAge": 60 * 60 * 24, + + "recompressStaticAssets": true, + + "logging": [], //re-add this feature later + + "keyGenerator": { + "type": "phonetic" + }, + + "rateLimits": { + "windowMs": 60 * 60 * 1000, + "max": 500 + }, + + "storage": { + "type": "file", + "path": "./data" + }, + + "documents": { + "about": "./about.md" + } +} \ No newline at end of file diff --git a/config.json b/config.json deleted file mode 100644 index 048b1d1..0000000 --- a/config.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - - "host": "127.0.0.1", - "port": 7777, - - "keyLength": 10, - - "maxLength": 400000, - - "staticMaxAge": 86400, - - "recompressStaticAssets": true, - - "logging": [ - { - "level": "verbose", - "type": "Console", - "colorize": true - } - ], - - "keyGenerator": { - "type": "phonetic" - }, - - "rateLimits": { - "categories": { - "normal": { - "totalRequests": 500, - "every": 60000 - } - } - }, - - "storage": { - "type": "file", - "path": "./data" - }, - - "documents": { - "about": "./about.md" - } - -} diff --git a/lib/document_handler.js b/lib/document_handler.js index 83eb141..c1860ed 100644 --- a/lib/document_handler.js +++ b/lib/document_handler.js @@ -1,12 +1,10 @@ -var winston = require('winston'); -var Busboy = require('busboy'); +const winston = require('winston'); +const Busboy = require('busboy'); // For handling serving stored documents -var DocumentHandler = function(options) { - if (!options) { - options = {}; - } +const DocumentHandler = function(options) { + if (!options) options = new Object; this.keyLength = options.keyLength || DocumentHandler.defaultKeyLength; this.maxLength = options.maxLength; // none by default this.store = options.store; @@ -16,98 +14,98 @@ var DocumentHandler = function(options) { DocumentHandler.defaultKeyLength = 10; // Handle retrieving a document -DocumentHandler.prototype.handleGet = function(key, response, skipExpire) { +DocumentHandler.prototype.handleGet = function(key, res, skipExpire) { this.store.get(key, function(ret) { if (ret) { winston.verbose('retrieved document', { key: key }); - response.writeHead(200, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ data: ret, key: key })); + res.writeHead(200, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ data: ret, key: key })); } else { winston.warn('document not found', { key: key }); - response.writeHead(404, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ message: 'Document not found.' })); + res.writeHead(404, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ message: 'Document not found.' })); } }, skipExpire); }; // Handle retrieving the raw version of a document -DocumentHandler.prototype.handleRawGet = function(key, response, skipExpire) { +DocumentHandler.prototype.handleGetRaw = function(key, res, skipExpire) { this.store.get(key, function(ret) { if (ret) { winston.verbose('retrieved raw document', { key: key }); - response.writeHead(200, { 'content-type': 'text/plain; charset=UTF-8' }); - response.end(ret); + res.writeHead(200, { 'content-type': 'text/plain; charset=UTF-8' }); + res.end(ret); } else { winston.warn('raw document not found', { key: key }); - response.writeHead(404, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ message: 'Document not found.' })); + res.writeHead(404, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ message: 'Document not found.' })); } }, skipExpire); }; // Handle adding a new Document -DocumentHandler.prototype.handlePost = function (request, response) { - var _this = this; - var buffer = ''; - var cancelled = false; +DocumentHandler.prototype.handlePost = function (req, res) { + let _this = this; + let buffer = ''; + let cancelled = false; // What to do when done - var onSuccess = function () { + let onSuccess = function () { // Check length if (_this.maxLength && buffer.length > _this.maxLength) { cancelled = true; winston.warn('document >maxLength', { maxLength: _this.maxLength }); - response.writeHead(400, { 'content-type': 'application/json' }); - response.end( + res.writeHead(400, { 'content-type': 'application/json' }); + res.end( JSON.stringify({ message: 'Document exceeds maximum length.' }) ); return; } // And then save if we should _this.chooseKey(function (key) { - _this.store.set(key, buffer, function (res) { - if (res) { + _this.store.set(key, buffer, function (resp) { + if (resp) { winston.verbose('added document', { key: key }); - response.writeHead(200, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ key: key })); + res.writeHead(200, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ key: key })); } else { winston.verbose('error adding document'); - response.writeHead(500, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ message: 'Error adding document.' })); + res.writeHead(500, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ message: 'Error adding document.' })); } }); }); }; // If we should, parse a form to grab the data - var ct = request.headers['content-type']; - if (ct && ct.split(';')[0] === 'multipart/form-data') { - var busboy = new Busboy({ headers: request.headers }); + let ct = req.headers['content-type']; + if (ct && ct.split(';')[0] == 'multipart/form-data') { + let busboy = new Busboy({ headers: req.headers }); busboy.on('field', function (fieldname, val) { - if (fieldname === 'data') { + if (fieldname == 'data') { buffer = val; } }); busboy.on('finish', function () { onSuccess(); }); - request.pipe(busboy); + req.pipe(busboy); // Otherwise, use our own and just grab flat data from POST body } else { - request.on('data', function (data) { + req.on('data', function (data) { buffer += data.toString(); }); - request.on('end', function () { + req.on('end', function () { if (cancelled) { return; } onSuccess(); }); - request.on('error', function (error) { + req.on('error', function (error) { winston.error('connection error: ' + error.message); - response.writeHead(500, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ message: 'Connection error.' })); + res.writeHead(500, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ message: 'Connection error.' })); cancelled = true; }); } @@ -115,8 +113,8 @@ DocumentHandler.prototype.handlePost = function (request, response) { // Keep choosing keys until one isn't taken DocumentHandler.prototype.chooseKey = function(callback) { - var key = this.acceptableKey(); - var _this = this; + let key = this.acceptableKey(); + let _this = this; this.store.get(key, function(ret) { if (ret) { _this.chooseKey(callback); diff --git a/lib/document_stores/amazon-s3.js b/lib/document_stores/amazon-s3.js index 11dd85d..6fd3673 100644 --- a/lib/document_stores/amazon-s3.js +++ b/lib/document_stores/amazon-s3.js @@ -1,18 +1,18 @@ /*global require,module,process*/ -var AWS = require('aws-sdk'); -var winston = require('winston'); +const AWS = require('aws-sdk'); +const winston = require('winston'); -var AmazonS3DocumentStore = function(options) { +const AmazonS3DocumentStore = function(options) { this.expire = options.expire; this.bucket = options.bucket; this.client = new AWS.S3({region: options.region}); }; AmazonS3DocumentStore.prototype.get = function(key, callback, skipExpire) { - var _this = this; + const _this = this; - var req = { + const req = { Bucket: _this.bucket, Key: key }; @@ -31,9 +31,9 @@ AmazonS3DocumentStore.prototype.get = function(key, callback, skipExpire) { } AmazonS3DocumentStore.prototype.set = function(key, data, callback, skipExpire) { - var _this = this; + const _this = this; - var req = { + const req = { Bucket: _this.bucket, Key: key, Body: data, diff --git a/lib/document_stores/file.js b/lib/document_stores/file.js index 7fd5995..db8d715 100644 --- a/lib/document_stores/file.js +++ b/lib/document_stores/file.js @@ -1,20 +1,20 @@ -var fs = require('fs'); -var crypto = require('crypto'); +const fs = require('fs'); +const crypto = require('crypto'); -var winston = require('winston'); +const winston = require('winston'); // For storing in files // options[type] = file // options[path] - Where to store -var FileDocumentStore = function(options) { +const FileDocumentStore = function(options) { this.basePath = options.path || './data'; this.expire = options.expire; }; // Generate md5 of a string FileDocumentStore.md5 = function(str) { - var md5sum = crypto.createHash('md5'); + let md5sum = crypto.createHash('md5'); md5sum.update(str); return md5sum.digest('hex'); }; @@ -23,9 +23,9 @@ FileDocumentStore.md5 = function(str) { // be passed here FileDocumentStore.prototype.set = function(key, data, callback, skipExpire) { try { - var _this = this; + const _this = this; fs.mkdir(this.basePath, '700', function() { - var fn = _this.basePath + '/' + FileDocumentStore.md5(key); + const fn = _this.basePath + '/' + FileDocumentStore.md5(key); fs.writeFile(fn, data, 'utf8', function(err) { if (err) { callback(false); @@ -45,8 +45,8 @@ FileDocumentStore.prototype.set = function(key, data, callback, skipExpire) { // Get data from a file from key FileDocumentStore.prototype.get = function(key, callback, skipExpire) { - var _this = this; - var fn = this.basePath + '/' + FileDocumentStore.md5(key); + const _this = this; + const fn = this.basePath + '/' + FileDocumentStore.md5(key); fs.readFile(fn, 'utf8', function(err, data) { if (err) { callback(false); diff --git a/lib/document_stores/postgres.js b/lib/document_stores/postgres.js index dbb471c..39c76c7 100644 --- a/lib/document_stores/postgres.js +++ b/lib/document_stores/postgres.js @@ -1,12 +1,12 @@ /*global require,module,process*/ -var postgres = require('pg'); -var winston = require('winston'); +const postgres = require('pg'); +const winston = require('winston'); // create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key)); // A postgres document store -var PostgresDocumentStore = function (options) { +const PostgresDocumentStore = function (options) { this.expireJS = options.expire; this.connectionUrl = process.env.DATABASE_URL || options.connectionUrl; }; @@ -15,8 +15,8 @@ PostgresDocumentStore.prototype = { // Set a given key set: function (key, data, callback, skipExpire) { - var now = Math.floor(new Date().getTime() / 1000); - var that = this; + const now = Math.floor(Date.now() / 1000); + const that = this; this.safeConnect(function (err, client, done) { if (err) { return callback(false); } client.query('INSERT INTO entries (key, value, expiration) VALUES ($1, $2, $3)', [ @@ -36,8 +36,8 @@ PostgresDocumentStore.prototype = { // Get a given key's data get: function (key, callback, skipExpire) { - var now = Math.floor(new Date().getTime() / 1000); - var that = this; + const now = Math.floor(Date.now() / 1000); + const that = this; this.safeConnect(function (err, client, done) { if (err) { return callback(false); } client.query('SELECT id,value,expiration from entries where KEY = $1 and (expiration IS NULL or expiration > $2)', [key, now], function (err, result) { diff --git a/lib/document_stores/redis.js b/lib/document_stores/redis.js index eed07e7..0ecb78d 100644 --- a/lib/document_stores/redis.js +++ b/lib/document_stores/redis.js @@ -1,5 +1,5 @@ -var redis = require('redis'); -var winston = require('winston'); +const redis = require('redis'); +const winston = require('winston'); // For storing in redis // options[type] = redis diff --git a/lib/key_generators/dictionary.js b/lib/key_generators/dictionary.js index 0bcbc2e..512a14f 100644 --- a/lib/key_generators/dictionary.js +++ b/lib/key_generators/dictionary.js @@ -4,7 +4,7 @@ module.exports = class DictionaryGenerator { constructor(options, readyCallback) { // Check options format - if (!options) throw Error('No options passed to generator'); + if (!options) throw Error('No options passed to generator'); if (!options.path) throw Error('No dictionary path specified in options'); // Load dictionary diff --git a/lib/key_generators/phonetic.js b/lib/key_generators/phonetic.js index f281f6b..71d1b26 100644 --- a/lib/key_generators/phonetic.js +++ b/lib/key_generators/phonetic.js @@ -15,7 +15,7 @@ module.exports = class PhoneticKeyGenerator { // Generate a phonetic key of alternating consonant & vowel createKey(keyLength) { let text = ''; - const start = Math.round(Math.random()); + const start = Math.floor(Math.random() * 2); for (let i = 0; i < keyLength; i++) { text += (i % 2 == start) ? randConsonant() : randVowel(); diff --git a/lib/key_generators/random.js b/lib/key_generators/random.js index 767e26b..62f19cb 100644 --- a/lib/key_generators/random.js +++ b/lib/key_generators/random.js @@ -7,9 +7,9 @@ module.exports = class RandomKeyGenerator { // Generate a key of the given length createKey(keyLength) { - var text = ''; + let text = ''; - for (var i = 0; i < keyLength; i++) { + for (let i = 0; i < keyLength; i++) { const index = Math.floor(Math.random() * this.keyspace.length); text += this.keyspace.charAt(index); } diff --git a/lib/util.js b/lib/util.js new file mode 100644 index 0000000..40c2501 --- /dev/null +++ b/lib/util.js @@ -0,0 +1,13 @@ +module.exports = class HasteUtils { + //init class + constructor(options = {}){ + //xd no options for now + } + + //stringify json objects from winston message to cool "key=value" format + stringifyJSONMessagetoLogs(info){ + //really KKona solution, but works for now + let keys = Object.keys(info).filter(k => k != 'message' && k != 'level'); + return keys.map(k => `${k}=${info[k]}`).join(', '); + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b9165ea..42a6c5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,12 +4,31 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -51,6 +70,11 @@ "sprintf-js": "~1.0.2" } }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, "array.prototype.map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", @@ -64,9 +88,9 @@ } }, "async": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", - "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, "async-cache": { "version": "1.1.0", @@ -107,27 +131,26 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } } } }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -175,6 +198,11 @@ "dicer": "0.3.0" } }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -246,6 +274,30 @@ } } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -258,13 +310,30 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "colors": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", - "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } }, "concat-map": { "version": "0.0.1", @@ -272,31 +341,40 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, - "connect-ratelimit": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/connect-ratelimit/-/connect-ratelimit-0.0.7.tgz", - "integrity": "sha1-5uCclQZJ6ElJnKsYcKQVoH9zFWg=" + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, - "connect-route": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/connect-route/-/connect-route-0.1.5.tgz", - "integrity": "sha1-48IYMZ0uiKiprgsOD+Cacpw5dEo=" + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "debug": { "version": "2.6.9", @@ -326,6 +404,16 @@ "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, "dicer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", @@ -351,6 +439,11 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -432,16 +525,75 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "express-rate-limit": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.1.3.tgz", + "integrity": "sha512-TINcxve5510pXj4n9/1AMupkj3iWxl3JuZaWhCdYDlZeoCPqweGZrxbrlqTCFb1CT5wli7s8e2SH/Qz2c9GorA==" + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, "fd": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/fd/-/fd-0.0.3.tgz", "integrity": "sha512-iAHrIslQb3U68OcMSP0kkNWabp7sSN6d2TBSb2JO3gcLJVDd4owr/hKM4SFJovFOUeeXeItjYgouEDTMWiVAnA==" }, + "fecha": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -484,6 +636,21 @@ "is-buffer": "~2.0.3" } }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -571,6 +738,26 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -589,8 +776,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is-arguments": { "version": "1.0.4", @@ -598,6 +789,11 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -679,6 +875,11 @@ "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", "dev": true }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -694,6 +895,11 @@ "has-symbols": "^1.0.1" } }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -726,6 +932,11 @@ "esprima": "^4.0.0" } }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -744,6 +955,25 @@ "chalk": "^4.0.0" } }, + "logform": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -753,10 +983,38 @@ "yallist": "^2.1.2" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } }, "minimatch": { "version": "3.0.4", @@ -874,6 +1132,14 @@ "wrappy": "1" } }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, "p-limit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", @@ -920,6 +1186,11 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, "pg": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.2.tgz", @@ -981,11 +1252,6 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, - "pkginfo": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz", - "integrity": "sha1-cjnEKl72wwuPMoQ52bn/cQQkkPg=" - }, "postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -1009,6 +1275,11 @@ "xtend": "^4.0.0" } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "promise.allsettled": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", @@ -1022,11 +1293,25 @@ "iterate-value": "^1.0.0" } }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -1036,6 +1321,32 @@ "safe-buffer": "^5.1.0" } }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", @@ -1082,11 +1393,6 @@ "redis": ">= 0.0.1" } }, - "request": { - "version": "2.9.203", - "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz", - "integrity": "sha1-bBcRpUB/uUoRQhlWPkQUW8v0cjo=" - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -1104,11 +1410,43 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "semver": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, "serialize-javascript": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", @@ -1118,16 +1456,35 @@ "randombytes": "^2.1.0" } }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } }, "split": { "version": "1.0.1", @@ -1154,6 +1511,13 @@ "graceful-fs": "^4.2.3", "mime": "^2.4.4", "negotiator": "~0.6.2" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + } } }, "stack-trace": { @@ -1201,6 +1565,14 @@ "es-abstract": "^1.17.5" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -1225,6 +1597,11 @@ "has-flag": "^4.0.0" } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -1239,22 +1616,30 @@ "is-number": "^7.0.0" } }, - "uglify-js": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.1.6.tgz", - "integrity": "sha512-/rseyxEKEVMBo8279lqpoJgD6C/i/CIi+9TJDvWmb+Xo6mqMKwjA8Io3IMHlcXQzj99feR6zrN8m3wqqvm/nYA==", + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "requires": { - "commander": "~2.11.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" - } + "media-typer": "0.3.0", + "mime-types": "~2.1.24" } }, + "uglify-js": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.2.tgz", + "integrity": "sha512-GXCYNwqoo0MbLARghYjxVBxDCnU0tLqN7IPLdHHbibCb1NI5zBkU2EPcy/GaVxc0BtTjqyGXJCINe6JMR2Dpow==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1270,6 +1655,11 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1295,17 +1685,57 @@ } }, "winston": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-0.6.2.tgz", - "integrity": "sha1-QUT+JYbNwZphK/jANVkBMskGS9I=", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", "requires": { - "async": "0.1.x", - "colors": "0.x.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "pkginfo": "0.2.x", - "request": "2.9.x", - "stack-trace": "0.0.x" + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } + }, + "winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "requires": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "workerpool": { diff --git a/package.json b/package.json index c127087..7802b65 100644 --- a/package.json +++ b/package.json @@ -1,47 +1,46 @@ { - "name": "haste", - "version": "0.1.0", - "private": false, - "description": "Private Pastebin Server - continued by zneix", - "keywords": [ - "paste", - "pastebin" - ], - "author": { - "name": "John Crepezzi", - "email": "john.crepezzi@gmail.com", - "url": "http://seejohncode.com/" - }, - "main": "server.js", - "dependencies": { - "busboy": "^0.3.1", - "connect": "^3.7.0", - "connect-ratelimit": "0.0.7", - "connect-route": "0.1.5", - "pg": "^8.3.2", - "redis": "^3.0.2", - "redis-url": "^1.2.1", - "st": "^2.0.0", - "uglify-js": "3.1.6", - "winston": "^0.6.2" - }, - "devDependencies": { - "mocha": "^8.1.2" - }, - "bundledDependencies": [], - "bin": { - "haste-server": "./server.js" - }, - "files": [ - "server.js", - "lib", - "static" - ], - "directories": { - "lib": "./lib" - }, - "scripts": { - "start": "node server.js", - "test": "mocha --recursive" - } + "name": "haste", + "version": "0.2.0", + "description": "Private Pastebin Server - continued by zneix", + "keywords": [ + "paste", + "pastebin", + "haste", + "hastebin" + ], + "author": { + "name": "John Crepezzi", + "email": "john.crepezzi@gmail.com", + "url": "http://seejohncode.com/" + }, + "main": "server.js", + "dependencies": { + "busboy": "^0.3.1", + "express": "^4.17.1", + "express-rate-limit": "^5.1.3", + "pg": "^8.3.2", + "redis": "^3.0.2", + "redis-url": "^1.2.1", + "st": "^2.0.0", + "uglify-js": "^3.10.2", + "winston": "^3.3.3" + }, + "devDependencies": { + "mocha": "^8.1.2" + }, + "bin": { + "haste-server": "./server.js" + }, + "files": [ + "server.js", + "lib", + "static" + ], + "directories": { + "lib": "./lib" + }, + "scripts": { + "start": "node server.js", + "test": "mocha --recursive" + } } diff --git a/server.js b/server.js index aa4b5f2..f9c8a6e 100644 --- a/server.js +++ b/server.js @@ -1,155 +1,134 @@ -const http = require('http'); const fs = require('fs'); - -const uglify = require('uglify-js'); const winston = require('winston'); -const connect = require('connect'); -const route = require('connect-route'); -const connect_st = require('st'); -const connect_rate_limit = require('connect-ratelimit'); +const uglify = require('uglify-js'); +const st = require('st'); +const app = require('express')(); +const expressRateLimit = require('express-rate-limit'); const DocumentHandler = require('./lib/document_handler'); +const HasteUtils = require('./lib/util'); -// Load the configuration and set some defaults -const config = require('./config.json'); -config.port = process.env.PORT || config.port || 7777; -config.host = process.env.HOST || config.host || 'localhost'; +const utils = new HasteUtils(); -// Set up the logger -if (config.logging) { - try { - winston.remove(winston.transports.Console); - } catch(e) { - /* was not present */ - } +//set up logger +//only Console for now, gotta utilize config.json in the future +winston.add(new winston.transports.Console({ + level: 'silly', + format: winston.format.combine( + winston.format.colorize(), + winston.format.printf(info => `${info.level}: ${info.message} ${utils.stringifyJSONMessagetoLogs(info)}`) + ), +})); - let detail, type; - for (let i = 0; i < config.logging.length; i++) { - detail = config.logging[i]; - type = detail.type; - delete detail.type; - winston.add(winston.transports[type], detail); - } +//load config and set some defaults +const config = require('./config'); +config.port = config.port || 7777; +config.host = config.host || '127.0.0.1'; + +//defaulting storage type to file +if (!config.storage){ + config.storage = { + type: 'file', + path: './data' + }; } +if (!config.storage.type) config.storage.type = 'file'; -// build the store from the config on-demand - so that we don't load it -// for statics -if (!config.storage) { - config.storage = { type: 'file' }; -} -if (!config.storage.type) { - config.storage.type = 'file'; -} - -let Store, preferredStore; - -if (process.env.REDISTOGO_URL && config.storage.type === 'redis') { - let redisClient = require('redis-url').connect(process.env.REDISTOGO_URL); - Store = require('./lib/document_stores/redis'); - preferredStore = new Store(config.storage, redisClient); +let preferredStore; +if (process.env.REDISTOGO_URL && config.storage.type == 'redis'){ + let redisClient = require('redis-url').connect(process.env.REDISTOGO_URL); + let Store = require('./lib/document_stores/redis'); + preferredStore = new Store(config.storage, redisClient); } else { - Store = require('./lib/document_stores/' + config.storage.type); - preferredStore = new Store(config.storage); + let Store = require(`./lib/document_stores/${config.storage.type}`); + preferredStore = new Store(config.storage); } -// Compress the static javascript assets -if (config.recompressStaticAssets) { - let list = fs.readdirSync('./static'); - for (let j = 0; j < list.length; j++) { - let item = list[j]; - if ((item.indexOf('.js') === item.length - 3) && (item.indexOf('.min.js') === -1)) { - let dest = item.substring(0, item.length - 3) + '.min' + item.substring(item.length - 3); - let orig_code = fs.readFileSync('./static/' + item, 'utf8'); +//compress static javascript assets +if (config.recompressStaticAssets){ + let files = fs.readdirSync('./static'); + for (const file of files){ + if ((file.indexOf('.js') == file.length - 3) && (file.indexOf('.min.js') == -1)){ + let dest = `${file.substring(0, file.length - 3)}.min${file.substring(file.length - 3)}`; + let origCode = fs.readFileSync(`./static/${file}`, 'utf8'); - fs.writeFileSync('./static/' + dest, uglify.minify(orig_code).code, 'utf8'); - winston.info('compressed ' + item + ' into ' + dest); + fs.writeFileSync(`./static/${dest}`, uglify.minify(origCode).code, 'utf8'); + winston.info(`compressed ${file} into ${dest}`); + } } - } } -// Send the static documents into the preferred store, skipping expirations -let path, data; -for (let name in config.documents) { - path = config.documents[name]; - data = fs.readFileSync(path, 'utf8'); - winston.info('loading static document', { name: name, path: path }); - if (data) { - preferredStore.set(name, data, function(cb) { - winston.debug('loaded static document', { success: cb }); - }, true); - } - else { - winston.warn('failed to load static document', { name: name, path: path }); - } +//send the static documents into the preferred store, skipping expirations +for (const name in config.documents){ + let path = config.documents[name]; + winston.info('loading static document', { name: name, path: path }); + let data = fs.readFileSync(path, 'utf8'); + if (data){ + preferredStore.set(name, data, doc => winston.debug('loaded static document', { success: doc }), true); + } + else { + winston.warn('failed to load static document', { name: name, path: path }); + } } -// Pick up a key generator -let pwOptions = config.keyGenerator || {}; +//pick up a key generator +let pwOptions = config.keyGenerator || new Object; pwOptions.type = pwOptions.type || 'random'; -let gen = require('./lib/key_generators/' + pwOptions.type); -let keyGenerator = new gen(pwOptions); +let Gen = require(`./lib/key_generators/${pwOptions.type}`); +let keyGenerator = new Gen(pwOptions); -// Configure the document handler +//configure the document handler let documentHandler = new DocumentHandler({ - store: preferredStore, - maxLength: config.maxLength, - keyLength: config.keyLength, - keyGenerator: keyGenerator + store: preferredStore, + maxLength: config.maxLength, + keyLength: config.keyLength, + keyGenerator: keyGenerator }); -let app = connect(); +//rate limit all requests +if (config.rateLimits) app.use(expressRateLimit(config.rateLimits)); -// Rate limit all requests -if (config.rateLimits) { - config.rateLimits.end = true; - app.use(connect_rate_limit(config.rateLimits)); -} +//try API first -// first look at API calls -app.use(route(function(router) { - // get raw documents - support getting with extension - router.get('/raw/:id', function(request, response) { - let key = request.params.id.split('.')[0]; - let skipExpire = !!config.documents[key]; - return documentHandler.handleRawGet(key, response, skipExpire); - }); - // add documents - router.post('/documents', function(request, response) { - return documentHandler.handlePost(request, response); - }); - // get documents - router.get('/documents/:id', function(request, response) { - let key = request.params.id.split('.')[0]; - let skipExpire = !!config.documents[key]; - return documentHandler.handleGet(key, response, skipExpire); - }); +//get raw documents +app.get('/raw/:id', (req, res) => { + const key = req.params.id.split('.')[0]; + const skipExpire = Boolean(config.documents[key]); + return documentHandler.handleGetRaw(key, res, skipExpire); +}); + +//add documents +app.post('/documents', (req, res) => { + return documentHandler.handlePost(req, res); +}); + +//get documents +app.get('/documents/:id', (req, res) => { + const key = req.params.id.split('.')[0]; + const skipExpire = Boolean(config.documents[key]); + return documentHandler.handleGet(key, res, skipExpire); +}); + +//try static next +app.use(st({ + path: './static', + passthrough: true, + index: false })); -// Otherwise, try to match static files -app.use(connect_st({ - path: __dirname + '/static', - content: { maxAge: config.staticMaxAge }, - passthrough: true, - index: false -})); - -// Then we can loop back - and everything else should be a token, -// so route it back to / -app.use(route(function(router) { - router.get('/:id', function(request, response, next) { - request.sturl = '/'; +//then we can loop back - and everything else should be a token, +//so route it back to / +app.get('/:id', (req, res, next) => { + req.sturl = '/'; next(); - }); -})); +}); -// And match index -app.use(connect_st({ - path: __dirname + '/static', +//and match index +app.use(st({ content: { maxAge: config.staticMaxAge }, - index: 'index.html' + path: './static', + index: 'index.html' })); -http.createServer(app).listen(config.port, config.host); - -winston.info('listening on ' + config.host + ':' + config.port); +app.listen(config.port, config.host, () => winston.info(`listening on ${config.host}:${config.port}`)); \ No newline at end of file diff --git a/static/application.js b/static/application.js index d936cd9..2ed1869 100644 --- a/static/application.js +++ b/static/application.js @@ -27,7 +27,7 @@ haste_document.prototype.load = function(key, callback, lang) { _this.data = res.data; try { var high; - if (lang === 'txt') { + if (lang == 'txt') { high = { value: _this.htmlEscape(res.data) }; } else if (lang) { @@ -178,7 +178,7 @@ haste.extensionMap = { // If not found, return the type itself - which we'll place as the extension haste.prototype.lookupExtensionByType = function(type) { for (var key in haste.extensionMap) { - if (haste.extensionMap[key] === type) return key; + if (haste.extensionMap[key] == type) return key; } return type; }; @@ -266,7 +266,7 @@ haste.prototype.configureButtons = function() { label: 'Save', shortcutDescription: 'control + s', shortcut: function(evt) { - return evt.ctrlKey && (evt.keyCode === 83); + return evt.ctrlKey && (evt.keyCode == 83); }, action: function() { if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') { @@ -278,7 +278,7 @@ haste.prototype.configureButtons = function() { $where: $('#box2 .new'), label: 'New', shortcut: function(evt) { - return evt.ctrlKey && evt.keyCode === 78; + return evt.ctrlKey && evt.keyCode == 78; }, shortcutDescription: 'control + n', action: function() { @@ -289,7 +289,7 @@ haste.prototype.configureButtons = function() { $where: $('#box2 .duplicate'), label: 'Duplicate & Edit', shortcut: function(evt) { - return _this.doc.locked && evt.ctrlKey && evt.keyCode === 68; + return _this.doc.locked && evt.ctrlKey && evt.keyCode == 68; }, shortcutDescription: 'control + d', action: function() { @@ -300,7 +300,7 @@ haste.prototype.configureButtons = function() { $where: $('#box2 .raw'), label: 'Just Text', shortcut: function(evt) { - return evt.ctrlKey && evt.shiftKey && evt.keyCode === 82; + return evt.ctrlKey && evt.shiftKey && evt.keyCode == 82; }, shortcutDescription: 'control + shift + r', action: function() { @@ -366,7 +366,7 @@ haste.prototype.configureShortcuts = function() { $(function() { $('textarea').keydown(function(evt) { - if (evt.keyCode === 9) { + if (evt.keyCode == 9) { evt.preventDefault(); var myValue = ' '; // http://stackoverflow.com/questions/946534/insert-text-into-textarea-with-jquery diff --git a/static/application.min.js b/static/application.min.js deleted file mode 100644 index e30f711..0000000 --- a/static/application.min.js +++ /dev/null @@ -1 +0,0 @@ -var haste_document=function(){this.locked=!1};haste_document.prototype.htmlEscape=function(t){return t.replace(/&/g,"&").replace(/>/g,">").replace(/'+t+"");$("#messages").prepend(o),setTimeout(function(){o.slideUp("fast",function(){$(this).remove()})},3e3)},haste.prototype.lightKey=function(){this.configureKey(["new","save"])},haste.prototype.fullKey=function(){this.configureKey(["new","duplicate","twitter","raw"])},haste.prototype.configureKey=function(t){var e,o=0;$("#box2 .function").each(function(){for(e=$(this),o=0;o";$("#linenos").html(e)},haste.prototype.removeLineNumbers=function(){$("#linenos").html(">")},haste.prototype.loadDocument=function(t){var e=t.split(".",2),o=this;o.doc=new haste_document,o.doc.load(e[0],function(t){t?(o.$code.html(t.value),o.setTitle(t.key),o.fullKey(),o.$textarea.val("").hide(),o.$box.show().focus(),o.addLineNumbers(t.lineCount)):o.newDocument()},this.lookupTypeByExtension(e[1]))},haste.prototype.duplicateDocument=function(){if(this.doc.locked){var t=this.doc.data;this.newDocument(),this.$textarea.val(t)}},haste.prototype.lockDocument=function(){var t=this;this.doc.save(this.$textarea.val(),function(e,o){if(e)t.showMessage(e.message,"error");else if(o){t.$code.html(o.value),t.setTitle(o.key);var n="/"+o.key;o.language&&(n+="."+t.lookupExtensionByType(o.language)),window.history.pushState(null,t.appName+"-"+o.key,n),t.fullKey(),t.$textarea.val("").hide(),t.$box.show().focus(),t.addLineNumbers(o.lineCount)}})},haste.prototype.configureButtons=function(){var t=this;this.buttons=[{$where:$("#box2 .save"),label:"Save",shortcutDescription:"control + s",shortcut:function(t){return t.ctrlKey&&83===t.keyCode},action:function(){""!==t.$textarea.val().replace(/^\s+|\s+$/g,"")&&t.lockDocument()}},{$where:$("#box2 .new"),label:"New",shortcut:function(t){return t.ctrlKey&&78===t.keyCode},shortcutDescription:"control + n",action:function(){t.newDocument(!t.doc.key)}},{$where:$("#box2 .duplicate"),label:"Duplicate & Edit",shortcut:function(e){return t.doc.locked&&e.ctrlKey&&68===e.keyCode},shortcutDescription:"control + d",action:function(){t.duplicateDocument()}},{$where:$("#box2 .raw"),label:"Just Text",shortcut:function(t){return t.ctrlKey&&t.shiftKey&&82===t.keyCode},shortcutDescription:"control + shift + r",action:function(){window.location.href="/raw/"+t.doc.key}},{$where:$("#box2 .twitter"),label:"Twitter",shortcut:function(e){return t.options.twitter&&t.doc.locked&&e.shiftKey&&e.ctrlKey&&84==e.keyCode},shortcutDescription:"control + shift + t",action:function(){window.open("https://twitter.com/share?url="+encodeURI(window.location.href))}}];for(var e=0;e