Add files via upload

This commit is contained in:
Sophia Atkinson 2021-08-18 00:12:37 -07:00 committed by GitHub
parent ecd6246099
commit 9d759573d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 3098 additions and 0 deletions

18
bot/commands/banIP.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
command: 'banip',
description: 'Ban an IP Address from your service',
syntax: '{PREFIX}banip [IP_ADDRESS]',
execute: async (_this, msg, args) => {
if (!args.join(' ')) return msg.channel.createMessage('No arguments were given');
const ipAddress = args.join(' ');
const exists = _this.db.get('bans').find({ ip: ipAddress }).value();
if (exists === undefined) {
msg.channel.createMessage(`Banning IP \`${ipAddress}\`...`);
_this.db.get('bans')
.push({ ip: ipAddress })
.write();
} else {
msg.channel.createMessage('This IP Address is already banned');
}
},
};

View File

@ -0,0 +1,17 @@
const fs = require('fs');
module.exports = {
command: 'df',
description: 'Delete a file from your webserver (https://{domain}/{fileName})',
syntax: '{PREFIX}df [fileName]',
execute: async (_this, msg, args) => {
if (!args.join(' ')) return msg.channel.createMessage('No arguments were given');
const fileName = args.join(' ');
const filesDir = `${__dirname}/../../server/uploads`;
fs.unlink(`${filesDir}/${fileName}`, err => {
err
? msg.channel.createMessage(`Error deleting file: ${fileName}\n${err}`)
: msg.channel.createMessage(`Successfully Deleted File: ${fileName}`);
});
},
};

90
bot/commands/eval.js Normal file
View File

@ -0,0 +1,90 @@
/* eslint-disable no-param-reassign */
/* eslint-disable global-require */
/* eslint-disable no-extend-native */
/* eslint-disable no-eval */
module.exports = {
command: 'eval',
description: 'evaluate and execute javascript',
syntax: '{PREFIX}eval [code]',
execute: async (_this, msg, args) => {
String.prototype.charLimitSplit = number => {
if (typeof number !== 'number') {
// eslint-disable-next-line no-param-reassign
number = parseInt(number, 10);
}
const newSplit = [];
if (this.length > number) {
const splitRegex = new RegExp(`.{1,${number}}`, 'g');
const splitStr = this.match(splitRegex);
for (let i = 0; i < splitStr.length; i++) {
newSplit.push(splitStr[i]);
}
return newSplit;
}
};
const code = args.join(' ');
async function success(input, output) {
msg.channel.createMessage({
embed: {
color: 0x36393E,
fields: [{
name: 'Input',
value: `\`\`\`JS\n${input}\`\`\``,
}, {
name: 'Output',
value: `\`\`\`JS\n${output} | ... |\`\`\``,
}],
},
});
}
async function error(input, output) {
msg.channel.createMessage({
embed: {
color: 0x36393E,
fields: [{
name: 'Input',
value: `\`\`\`JS\n${input}\`\`\``,
}, {
name: 'Error Output',
value: `\`\`\`JS\n${output}\`\`\``,
}],
},
});
}
function clean(text) {
if (typeof (text) === 'string') {
text = text.replace(/`/g, `\`${String.fromCharCode(8203)}`).replace(/@/g, `@${String.fromCharCode(8203)}`);
const tokenObj = new RegExp(`${Buffer.from(_this.bot.user.id).toString('base64')}\\S+(?="|'|\`)`, 'gm');
const tokenRaw = new RegExp(`${Buffer.from(_this.bot.user.id).toString('base64')}\\S+`, 'gm');
if (text.match(tokenObj)) {
text = text.replace(tokenObj, 'Token Cleaned');
return text;
} if (text.match(tokenRaw)) {
text = text.replace(tokenRaw, 'Token Cleaned');
return text;
}
return text;
}
return text;
}
try {
let evaled = eval(code);
if (typeof evaled !== 'string') {
evaled = require('util').inspect(evaled, {
breakLength: Infinity,
});
}
if (evaled.length > 1000) {
const output = clean(evaled).charLimitSplit(1000);
return success(code, output[0]);
}
return success(code, clean(evaled));
} catch (err) {
if (err.length > 1000) {
const errorSplit = err.charLimitSplit(1000);
return error(code, errorSplit);
}
return error(code, clean(err));
}
},
};

18
bot/commands/exec.js Normal file
View File

@ -0,0 +1,18 @@
const { exec } = require('child_process');
module.exports = {
command: 'exec',
description: 'execute terminal commands from Discord',
syntax: '{PREFIX}exec [cmds]',
execute: async (_this, msg, args) => {
if (!args.join(' ')) return msg.channel.createMessage('No arguments were given');
msg.channel.createMessage(`\`INPUT\`\n\`\`\`ini\n${args.join(' ')}\n\`\`\``);
exec(args.join(' '), (error, stdout) => {
if (error) {
msg.channel.createMessage(`\`ERROR\`\n\`\`\`ini\n${error}\n\`\`\``);
} else {
msg.channel.createMessage(`\`OUTPUT\`\n\`\`\`ini\n${stdout}\n\`\`\``);
}
});
},
};

12
bot/commands/help.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
command: 'help',
description: 'Get info on commands',
syntax: '{PREFIX}help',
execute: async (_this, msg) => {
const cmds = [];
_this.commands.map(cmd => {
cmds.push(`[${cmd.command}]: ${cmd.syntax.replace('{PREFIX}', _this.c.prefix)} | ${cmd.description}`);
});
msg.channel.createMessage(`Here is a list of available commands\n\`\`\`ini\n${cmds.join('\n')}\n\`\`\``);
},
};

View File

@ -0,0 +1,25 @@
module.exports = {
command: 'rv',
description: 'Displays recent visitors',
syntax: '{PREFIX}rv',
execute: async (_this, msg) => {
const visitors = _this.db.get('visitors').value();
if (visitors === undefined) {
msg.channel.createMessage('Your site has no visitors');
} else {
const recent = visitors.map(e => e.date).sort().reverse();
const visitorsCollection = [];
let maximum;
recent.length > 10
? maximum = 10
: maximum = recent.length;
for (let i = 0; i < maximum; i++) {
const targetData = _this.db.get('visitors').find({ date: recent[i] }).value();
visitorsCollection.push(`[IP]: ${targetData.ip}\n[Page]: ${targetData.path}`);
if (i + 1 >= maximum) {
msg.channel.createMessage(`**ShareX Server Recent Visitors**\n\`\`\`ini\n${visitorsCollection.join('\n\n')}\n\`\`\``);
}
}
}
},
};

19
bot/commands/rename.js Normal file
View File

@ -0,0 +1,19 @@
const fs = require('fs');
module.exports = {
command: 'rn',
description: 'Rename an upload',
syntax: '{PREFIX}rn [old fileName], [new file name]',
execute: async (_this, msg, args) => {
// eslint-disable-next-line no-useless-escape
const files = args.join(' ').split(/\, ?/);
if (!files[0]) return msg.channel.createMessage('Supply a file name');
if (!files[1]) return msg.channel.createMessage('Supply a new file name');
const filesDir = `${__dirname}/../../server/uploads`;
fs.rename(`${filesDir}/${files[0]}`, `${filesDir}/${files[1]}`, err => {
err
? msg.channel.createMessage(`Error renaming file: ${files[0]}\n${err}`)
: msg.channel.createMessage(`Successfully Renamed File: ${files[1]}`);
});
},
};

10
bot/commands/restart.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
command: 'restart',
description: 'restart the webserver',
syntax: '{PREFIX}restart',
execute: async (_this, msg) => {
msg.channel.createMessage('Restarting...').then(() => {
process.exit();
});
},
};

View File

@ -0,0 +1,22 @@
module.exports = {
command: 'trafficfor',
description: 'Find amount of traffic for a specific month',
syntax: '{PREFIX}trafficfor [Month] [Year(optional)]',
execute: async (_this, msg, args) => {
if (!args.join(' ')) return msg.channel.createMessage('No arguments were given');
const month = args[0].toLowerCase();
let year;
args[1]
? year = `/${args[1]}`
: year = `/${new Date().getFullYear()}`;
const months = ['january', 'febuary', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
if (!months.includes(month)) return msg.channel.createMessage('This is not a month.');
const selectedMonth = `${months.indexOf(month) + 1}${year}`;
const traffic = _this.db.get('trafficTotal').find({ month: selectedMonth }).value();
if (traffic === undefined) {
msg.channel.createMessage('There has not been any traffic for this month');
} else {
msg.channel.createMessage(`There have been a total of \`${traffic.total}\` views of your site this month..`);
}
},
};

18
bot/commands/unbanIP.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
command: 'unbanip',
description: 'Unban an IP Address from your service',
syntax: '{PREFIX}unbanip [IP_ADDRESS]',
execute: async (_this, msg, args) => {
if (!args.join(' ')) return msg.channel.createMessage('No arguments were given');
const ipAddress = args.join(' ');
const exists = _this.db.get('bans').find({ ip: ipAddress }).value();
if (exists === undefined) {
msg.channel.createMessage('This IP Address is not banned');
} else {
msg.channel.createMessage(`Removing ban for IP \`${ipAddress}\`...`);
_this.db.get('bans')
.remove({ ip: ipAddress })
.write();
}
},
};

6
bot/events/index.js Normal file
View File

@ -0,0 +1,6 @@
require('fs')
.readdirSync(__dirname)
.map(filename => {
const moduleName = filename.split('.')[0];
exports[moduleName] = require(`${__dirname}/${filename}`);
});

View File

@ -0,0 +1,12 @@
async function messageCreate(msg) {
if (!this.c.discordAdminIDs.includes(msg.author.id)) return;
if (msg.content.indexOf(this.c.prefix) !== 0) return;
const args = msg.content.slice(this.c.prefix.length).trim().split(/ +/g);
const command = args.shift().toString().toLowerCase();
for (let i = 0; this.commands.length > i; i++) {
if (this.commands[i].command === command) {
this.commands[i].execute(this, msg, args);
}
}
}
module.exports = messageCreate;

5
bot/events/ready.js Normal file
View File

@ -0,0 +1,5 @@
async function ready() {
this.log.success('Discord API monitor successfully logged in');
this.monitorChannel = this.c.discordChannelID;
}
module.exports = ready;

309
server/app.js Normal file
View File

@ -0,0 +1,309 @@
/* eslint-disable consistent-return */
const express = require('express');
const fs = require('fs-extra');
const app = express();
const bodyParser = require('body-parser');
const Eris = require('eris');
const path = require('path');
const utils = require(`${__dirname}/../util`);
const routes = require(`${__dirname}/routes`);
const https = require('https');
const events = require(`${__dirname}/../bot/events`);
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('db.json');
const db = low(adapter);
const helmet = require('helmet');
/** Express Webserver Class */
class ShareXAPI {
/**
* Starting server and bot, handling routing, and middleware
* @param {object} c - configuration json file
*/
constructor(c) {
this.db = db;
/** Setting LowDB Defaults */
db.defaults({
files: [],
bans: [],
visitors: [],
trafficTotal: [],
passwordUploads: [],
})
.write();
/** Defintions */
this.utils = utils;
this.log = utils.log;
this.auth = utils.auth;
this.randomToken = utils.randomToken;
this.mimeType = utils.mimeType;
this.c = c;
this.monitorChannel = null;
this.checkMonth();
this.c.discordToken && this.c.discordToken !== undefined && this.c.discrdToken !== null
? this.runDiscordBot()
: this.log.verbose('No Discord Token provided...\nContinuing without Discord connection...');
this.app = app;
this.app.set('view engine', 'ejs');
this.app.set('views', path.join(__dirname, '/views'));
this.app.use(helmet());
this.app.use(bodyParser.text());
this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({
extended: true,
}));
/* Don't allow access if not accessed with configured domain */
this.app.use((req, res, next) => {
if(this.c.domain === '*') {
next();
} else if(req.headers.host !== this.c.domain.toLowerCase() && !this.c.domain.includes('*')) {
res.statusCode = 401;
res.write('Error 401: Unauthorized Domain');
return res.end();
} else if(this.c.domain.includes('*')) {
let reqParts = req.headers.host.toLowerCase().split('.');
let domainParts = this.c.domain.toLowerCase().split('.')
if(reqParts[1] === domainParts[1] && reqParts[2] === domainParts[2]) {
next();
} else {
res.statusCode = 401;
res.write('Error 401: Unauthorized Domain');
return res.end();
}
} else {
next();
}
});
/** Checking to see if IP is banned */
this.app.use((req, res, next) => {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
const exists = this.db.get('bans').find({ ip: userIP }).value();
if (exists === undefined) { // if a ban was not found, then it will move on
next();
} else {
res.statusCode = 401;
res.render('unauthorized');
return res.end();
}
});
/** Set to place IPs in temporarily for ratelimiting uploads */
const ratelimited = new Set();
this.app.use((req, res, next) => {
if (req.method === 'POST') {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
if (ratelimited.has(userIP)) {
res.statusCode = 429;
res.write('Error 429: Ratelimited');
return res.end();
}
next(); // Move on if IP is not in ratelimited set
ratelimited.add(userIP);
// delete IP from ratelimit set after time specified in config.json
setTimeout(() => ratelimited.delete(userIP), c.ratelimit);
} else {
next(); // move on if request type is not POST
}
});
this.app.use((req, res, next) => {
if (req.method === 'GET') {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
let file = req.path;
// Not ignoring these files causes bloat in the db
const ignored = ['/favicon.ico', '/assets/css/styles.min.css', '/highlight.pack.js', '/highlightjs-line-numbers.min.js', '/paste.css', '/atom-one-dark.css'];
let exists = this.db.get('files').find({ path: file }).value();
// making sure ignored files aren't included
if (ignored.includes(file)) exists = true;
if (exists === undefined) {
next(); // Move on if it doesn't exist, then input data into db
this.db.get('files')
.push({ path: file, ip: 'Unknown', views: 0 })
// Set IP to unknown in case a file is visited, and not uploaded using /api/files
.write();
if (!ignored.includes(file)) {
this.db.get('visitors')
.push({ date: new Date(), ip: userIP, path: file })
.write(); // Sets correct information for files uploaded with /api/files
}
} else {
next(); // Move on if the file already exists
const trafficPeriod = this.trafficPeriod(); // Gets month and year for tracking
let viewCount;
let trafficCount;
const filesExist = this.db.get('files').find({ path: file }).value(); // traffic exists for this file
const trafficExists = this.db.get('trafficTotal').find({ month: trafficPeriod }).value(); // traffic exists for this month and year
const visitors = this.db.get('visitors').value();
// Resetting visitors in the DB every 100 requests so the DB doesn't get bloated
if (visitors.length > 100) {
this.db.set('visitors', [])
.write();
}
filesExist === undefined
? viewCount = 0
: viewCount = filesExist.views + 1;
trafficExists === undefined
? trafficCount = 0
: trafficCount = trafficExists.total + 1;
this.db.get('files')
.find({ path: file })
.assign({ views: viewCount })
.write(); // Setting viewcount for file
if (!ignored.includes(file)) {
this.db.get('visitors')
.push({ date: new Date(), ip: userIP, path: file })
.write(); // Adding vsitor information to DB
}
if (!ignored.includes(file)) {
this.db.get('trafficTotal')
.find({ month: trafficPeriod })
.assign({ total: trafficCount })
.write(); // if request isn't to an ignored file, take request into total traffic
}
}
} else {
next();
}
});
// All files in /uploads/ are publicly accessible via http
this.app.use(express.static(`${__dirname}/uploads/`, {
extensions: this.c.admin.allowed.includes("*") ? null : this.c.admin.allowed,
}));
this.app.use(express.static(`${__dirname}/views/`, {
extensions: ['css'],
}));
// routing
this.app.get('/', routes.upload.bind(this));
this.app.get('/gallery', routes.gallery.get.bind(this));
this.app.get('/short', routes.short.get.bind(this));
this.app.get('/upload', routes.upload.bind(this));
this.app.get('/ERR_FILE_TOO_BIG', routes.fileTooBig.bind(this));
this.app.get('/ERR_ILLEGAL_FILE_TYPE', routes.illegalFileType.bind(this));
this.app.get('*', routes.err404.bind(this));
this.app.post('/api/shortener', routes.shortener.bind(this));
this.app.post('/short', routes.short.post.bind(this));
this.app.post('/gallery', routes.gallery.post.bind(this));
this.app.post('/pupload', routes.pupload.bind(this));
this.app.post('/api/paste', routes.paste.bind(this));
this.app.post('/api/files', routes.files.bind(this));
// Begin server
this.startServer();
}
/** Booting up the Discord Bot
* @returns {void}
*/
async runDiscordBot() {
this.bot = new Eris(this.c.discordToken, {
maxShards: 'auto',
});
this.log.verbose('Connecting to Discord...');
this.commands = [];
this.loadCommands();
this.bot
.on('messageCreate', events.messageCreate.bind(this))
.on('ready', events.ready.bind(this));
this.bot.connect();
}
/** Loads the commands for the discord bot to use in /bot/commands
* into an array defined before the calling of this function
* @returns {void}
*/
async loadCommands() {
fs.readdir(`${__dirname}/../bot/commands`, (err, files) => {
/** Commands are pushed to an array */
files.forEach(file => {
if (file.toString().includes('.js')) {
// eslint-disable-next-line global-require
this.commands.push(require(`${__dirname}/../bot/commands/${file.toString()}`));
this.log.verbose(`Loaded Command: ${file.toString()}`);
}
});
});
}
/** Start's the Express server
* @returns {void}
*/
async startServer() {
if (this.c.secure) {
/** if the secure option is set to true in config,
* it will boot in https so long as it detects
* key.pem and cert.pem in the src directory
*/
if (fs.existsSync(`${__dirname}/../key.pem`) && fs.existsSync(`${__dirname}/../cert.pem`)) {
const privateKey = fs.readFileSync(`${__dirname}/../key.pem`);
const certificate = fs.readFileSync(`${__dirname}/../cert.pem`);
https.createServer({
key: privateKey,
cert: certificate,
}, this.app).listen(this.c.securePort, '0.0.0.0');
} else {
// CF Flexible SSL
/** if no key & cert pem files are detected,
* it will still run in secure mode (returning urls with https)
* so that it's compatible with CF flexible SSL
* and SSL configurations via a reverse proxy */
this.app.listen(this.c.securePort, '0.0.0.0', () => {
this.log.warning('Server using flexible SSL secure setting\nTo run a full SSL setting, ensure key.pem and cert.pem are in the /src folder');
});
}
this.log.success(`Secure server listening on port ${this.c.securePort}`);
} else {
this.app.listen(this.c.port, '0.0.0.0', () => {
this.log.success(`Server listening on port ${this.c.port}`);
});
}
}
/** Checks to see if any DB entry is available for this month and year
* Then inserts a new object into the array if no data is available for
* that month/year
* @returns {void}
*/
async checkMonth() {
const trafficPeriod = this.trafficPeriod();
const dbMonth = this.db.get('trafficTotal').find({ month: trafficPeriod }).value();
if (dbMonth === undefined) {
this.db.get('trafficTotal')
.push({ month: trafficPeriod, total: 0 })
.write();
}
}
/** Gets the current month, and the current year
* then combines the two into a string
* this string is inserted into the database to be used
* for collecting traffic data on a per month basis
* @returns {string} 4/2019
*/
// eslint-disable-next-line class-methods-use-this
trafficPeriod() {
const date = new Date();
const currentMonth = date.getMonth() + 1;
const currentYear = date.getFullYear();
return `${currentMonth}/${currentYear}`;
}
/** Checks to see if server administrator wants to return http or https
* Using this function instead of req.secure because of
* Certain possible SSL configurations (CF Flexible SSL)
* @returns {string} http OR https
*/
protocol() {
if (this.c.secure) {
return 'https';
}
return 'http';
}
}
module.exports = ShareXAPI;

7
server/routes/err404.js Normal file
View File

@ -0,0 +1,7 @@
async function err404(req, res) {
res.setHeader('Content-Type', 'text/html');
res.statusCode = 404;
res.render('404');
res.end();
}
module.exports = err404;

View File

@ -0,0 +1,7 @@
async function fileTooBig(req, res) {
res.setHeader('Content-Type', 'text/html');
res.statusCode = 413;
res.render('ERR_FILE_TOO_BIG');
res.end();
}
module.exports = fileTooBig;

267
server/routes/files.js Normal file
View File

@ -0,0 +1,267 @@
/* eslint-disable no-lonely-if */
const formidable = require('formidable');
const fs = require('fs-extra');
const { Remarkable } = require('remarkable');
const ejs = require('ejs');
const exif = require('exif2');
const md = new Remarkable('full', {
html: false,
linkify: true,
typographer: true,
});
async function files(req, res) {
res.setHeader('Content-Type', 'text/text');
const fileName = this.randomToken(this.c.fileNameLength, false);
const form = new formidable.IncomingForm();
const protocol = this.protocol();
// eslint-disable-next-line no-shadow
form.parse(req, (err, fields, files) => {
let userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress.split(",")[0]; userIP = userIP.split(",")[0];
const authKey = fields.key;
let usingUploader = false;
if (files.fdataUploader && !fields.key) {
usingUploader = true;
// eslint-disable-next-line no-param-reassign
files.fdata = files.fdataUploader;
}
if (files.file) {
files.fdata = files.file;
}
if (!this.auth(this.c.key, fields.key, this.c) && usingUploader === false) {
res.statusCode = 401;
res.write('Unauthorized');
res.end();
return this.log.warning(`Unauthorized User | File Upload | ${userIP} | ${authKey}`);
} if (!this.auth(this.c.key, fields.password, this.c) && usingUploader === true) {
this.log.warning(this.auth(this.c.key, fields.password, this.c));
res.statusCode = 401;
res.redirect('/?error=Incorrect_Password');
res.end();
return this.log.warning(`Unauthorized User | File Upload | ${userIP} | ${authKey}`);
}
const oldpath = files.fdata.path;
const fileExt = files.fdata.name.substring(files.fdata.name.lastIndexOf('.') + 1, files.fdata.name.length).toLowerCase();
let newpath;
if(this.c.dateURLPath === true) {
let currentMonth = getDate('month')
let currentYear = getDate('year')
let currentDay = getDate('day')
let baseDir = `${__dirname}/../uploads/`
let basePWDir = `${__dirname}/../passwordUploads/`
fs.access(`${baseDir}${currentYear}/${currentMonth}/${currentDay}`, err => {
if (err && err.code === 'ENOENT') {
fs.mkdirSync(`${baseDir}${currentYear}`);
fs.mkdirSync(`${baseDir}${currentYear}/${currentMonth}`);
fs.mkdirSync(`${baseDir}${currentYear}/${currentMonth}/${currentDay}`)
}
});
fs.access(`${basePWDir}${currentYear}/${currentMonth}/${currentDay}`, err => {
if (err && err.code === 'ENOENT') {
fs.mkdirSync(`${basePWDir}${currentYear}`);
fs.mkdirSync(`${basePWDir}${currentYear}/${currentMonth}`);
fs.mkdirSync(`${basePWDir}${currentYear}/${currentMonth}/${currentDay}`)
}
});
}
fields.pupload
? newpath = `${__dirname}/../passwordUploads/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${fileName}.${fileExt}`
: newpath = `${__dirname}/../uploads/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${fileName}.${fileExt}`;
let returnedFileName;
if (!fileExt.includes('png') && !fileExt.includes('jpg') && !fileExt.includes('jpeg') && !fileExt.includes('md') && !fields.pupload) {
returnedFileName = `${fileName}.${fileExt}`;
} else {
returnedFileName = fileName;
}
if(fields.showCase) {
fields.showCase = true
}
let showCaseFile;
if(fields.showCase !== false) {
showCaseFile = this.randomToken(this.c.fileNameLength, false);
}
this.db.get('files')
.push({
path: fields.showCase ? `/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${showCaseFile}` : `/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName}`,
ip: userIP,
views: 0,
original: newpath,
showCase: fields.showCase ? true : false
})
.write();
let settings;
let isAdmin = false;
if (!this.c.admin.key.includes(fields.key)) {
settings = this.c;
} else {
settings = this.c.admin;
isAdmin = true;
}
if (Math.round((files.fdata.size / 1024) / 1000) > settings.maxUploadSize && !isAdmin) {
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[FAILED UPLOAD][USER]\n[FILE](${files.fdata.name})\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[TYPE](${files.fdata.type})\n[KEY](${authKey})\n[IP](${userIP})\n\n[ERROR](ERR_FILE_TOO_BIG)\`\`\``);
res.statusCode = 413;
if (usingUploader === true) {
res.redirect('/?error=File_Too_Big');
return res.end();
}
res.write(`${protocol}://${req.headers.host}/ERR_FILE_TOO_BIG`);
return res.end();
}
if (!settings.allowed.some(ext => fileExt.endsWith(ext)) && !settings.allowed.includes("*")) {
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[FAILED UPLOAD][USER]\n[FILE](${files.fdata.name})\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[TYPE](${files.fdata.type})\n[KEY](${authKey})\n[IP](${userIP})\n\n[ERROR](ERR_ILLEGAL_FILE_TYPE)\`\`\``);
res.statusCode = 415;
if (usingUploader === true) {
res.redirect('/?error=Illegal_File_Type');
return res.end();
}
res.write(`${protocol}://${req.headers.host}/ERR_ILLEGAL_FILE_TYPE`);
return res.end();
}
if (fields.pupload) {
let altKey = this.randomToken(this.c.puploadKeyGenLength, true);
fs.move(oldpath, newpath, () => {
let puploadKey
if(fields.pupload === '*random*') {
puploadKey = altKey;
} else {
puploadKey = fields.pupload;
}
this.db.get('passwordUploads')
.push({
fileName: `${fileName}.${fileExt}`,
key: puploadKey,
})
.write();
fs.readFile(newpath, 'utf-8', () => {
const stream = fs.createWriteStream(`${__dirname}/../uploads/${fileName}.html`);
stream.once('open', () => {
ejs.renderFile(`${__dirname}/../views/puploadAuth.ejs`, {
fileName: `${fileName}.${fileExt}`,
}, {}, (_err, str) => {
stream.write(str);
});
stream.end();
});
});
});
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[NEW UPLOAD][USER]\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[TYPE](${files.fdata.type})\n[KEY](${authKey})\n[IP](${userIP})\n\`\`\`\n${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName}`);
if (err) return res.write(err);
this.log.verbose(`New File Upload: ${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName} | IP: ${userIP} | KEY: ${authKey}`);
if (usingUploader === true) {
res.redirect(`/?success=${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName}`);
return res.end();
}
fields.pupload === '*random*' ? res.write(`URL: ${protocol}://${req.headers.host}/${returnedFileName} | KEY: ${altKey}`) : res.write(`${protocol}://${req.headers.host}/${returnedFileName}`);
return res.end();
}
if (fields.showCase === true) {
if(fileExt === "png" || fileExt === "jpg" || fileExt === "gif" || fileExt === "jpeg") {
returnedFileName = `${showCaseFile}.html`
fs.move(oldpath, newpath, () => {
fs.readFile(newpath, 'utf-8', (err, data) => {
exif(newpath, (err, obj) => {
if(!obj['camera model name']) obj['camera model name'] = "N/A";
if(!obj['f number']) obj['f number'] = "N/A";
if(!obj['exposure time']) obj['exposure time'] = "N/A";
if(!obj['iso']) obj['iso'] = "N/A";
if(!obj['focal length']) obj['focal length'] = "N/A";
if(!obj['image size']) obj['image size'] = "N/A";
if(!obj['lens id']) obj['lens id'] = "N/A";
let camera = obj['camera model name'].replace(/<|>|&lt;|&gt;/gm, "")
let fstop = `f/${obj['f number']}`.replace(/<|>|&lt;|&gt;/gm, "")
let shutter = obj['exposure time'].replace(/<|>|&lt;|&gt;/gm, "")
let iso = obj['iso'].replace(/<|>|&lt;|&gt;/gm, "")
let focal = obj['focal length'].replace(/<|>|&lt;|&gt;/gm, "")
let dims = obj['image size'].replace(/<|>|&lt;|&gt;/gm, "")
let lens = obj['lens id'].replace(/<|>|&lt;|&gt;/gm, "")
let width = parseInt(dims.split('x')[0]);
let height = parseInt(dims.split('x')[1]);
if(height > 700) {
let magicNumber = height / 700;
height = height / magicNumber;
width = width / magicNumber
}
let sizing = [width, height]
const stream = fs.createWriteStream(`${__dirname}/../uploads/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${showCaseFile}.html`);
stream.once('open', () => {
ejs.renderFile(`${__dirname}/../views/photoShowCase.ejs`, {
camera: camera,
fstop, fstop,
shutter, shutter,
iso: iso,
focal: focal,
dims: dims,
lens: lens,
width: sizing[0],
height: sizing[1],
filename: `${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${fileName}.${fileExt}`
}, {}, (_err, str) => {
stream.write(str);
});
stream.end();
});
});
});
});
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[NEW UPLOAD][USER]\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[TYPE](${files.fdata.type})\n[KEY](${authKey})\n[IP](${userIP})\n\`\`\`\n${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${showCaseFile}`);
if (err) return res.write(err);
this.log.verbose(`New File Upload: ${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${showCaseFile} | IP: ${userIP} | KEY ${authKey}`);
if (usingUploader === true) {
res.redirect(`/?success=${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${showCaseFile}`);
return res.end();
}
res.write(`${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${showCaseFile}`);
return res.end();
}
}
fs.move(oldpath, newpath, () => {
if (fileExt.toLowerCase() === 'md' && this.c.markdown) {
fs.readFile(newpath, 'utf-8', (_readErr, data) => {
const stream = fs.createWriteStream(`${__dirname}/../uploads/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${fileName}.html`);
stream.once('open', () => {
ejs.renderFile(`${__dirname}/../views/md.ejs`, {
ogDesc: data.match(/.{1,297}/g)[0],
mdRender: md.render(data),
}, {}, (_renderErr, str) => {
stream.write(str);
});
stream.end();
fs.unlink(newpath, delErr => {
if (delErr) return this.log.warning(delErr);
});
});
});
}
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[NEW UPLOAD][USER]\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[TYPE](${files.fdata.type})\n[IP](${userIP})\n[KEY](${authKey})\n\`\`\`\n${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName}`);
if (err) return res.write(err);
this.log.verbose(`New File Upload: ${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName} | IP: ${userIP} | KEY: ${authKey}`);
if (usingUploader === true) {
res.redirect(`/?success=${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName}`);
return res.end();
}
res.write(`${protocol}://${req.headers.host}/${this.c.dateURLPath === true ? `${getDate('year')}/${getDate('month')}/${getDate('day')}/`: ""}${returnedFileName}`);
return res.end();
});
});
}
//const currentMonth = date.getMonth() + 1;
function getDate(type) {
if(type.toLowerCase() === 'year') {
const date = new Date();
const currentYear = date.getFullYear();
return currentYear;
}
if(type.toLowerCase() === 'month') {
const date = new Date();
let currentMonth = `${date.getMonth() + 1}`;
if(currentMonth.length === 1) currentMonth = `0${currentMonth}`
return currentMonth;
}
if(type.toLowerCase() === 'day') {
const date = new Date();
let currentDay = `${date.getDate()}`;
if(currentDay.length === 1) currentDay = `0${currentDay}`;
return currentDay;
}
}
module.exports = files;

51
server/routes/gallery.js Normal file
View File

@ -0,0 +1,51 @@
const fs = require('fs-extra');
async function get(_req, res) {
res.setHeader('Content-Type', 'text/html');
res.render('galleryLogin');
res.end();
}
async function post(req, res) {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
res.setHeader('Content-Type', 'text/html');
const protocol = this.protocol();
var password = this.c.admin.key;
// Compatibility with old config
if(typeof password == "string"){
password = [password];
}
if (!this.c.admin.key.includes(req.body.password)) {
res.statusCode = 401;
res.render('unauthorized');
res.end();
return this.log.warning(`Unauthorized User | Gallery Access | ${userIP} | ${req.body.password}`);
}
this.log.warning(`IP Address: ${userIP} successfully accessed gallery with key ${req.body.password}`);
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[GALLERY ACCESS][USER]\n[IP](${userIP})\n[KEY](${req.body.password})\n\`\`\``);
fs.readdir(`${__dirname}/../uploads`, (err, files) => {
let pics = [];
files = files.map(fileName => {
return {
name: fileName,
time: fs.statSync(`${__dirname}/../uploads/${fileName}`).mtime.getTime()
};
})
files.sort((a, b) => {
return b.time - a.time; });
files = files.map(v => {
return v.name; });
files.forEach((file, idx, array) => {
if (file.toString().includes('.jpg') || file.toString().includes('.png') || file.toString().includes('.gif')) {
pics.push(`${protocol}://${req.headers.host}/${file.toString()}`);
}
if (idx === array.length - 1) {
res.render('gallery', {
pictures: pics,
});
return res.end();
}
})
});
}
module.exports = { get, post };

View File

@ -0,0 +1,7 @@
async function illegalFileType(req, res) {
res.setHeader('Content-Type', 'text/html');
res.statusCode = 413;
res.render('ERR_FILE_TOO_BIG');
res.end();
}
module.exports = illegalFileType;

7
server/routes/index.js Normal file
View File

@ -0,0 +1,7 @@
require('fs')
.readdirSync(__dirname)
.map(filename => {
const moduleName = filename.split('.')[0];
// eslint-disable-next-line global-require
exports[moduleName] = require(`${__dirname}/${filename}`);
});

59
server/routes/paste.js Normal file
View File

@ -0,0 +1,59 @@
/* eslint-disable consistent-return */
const formidable = require('formidable');
const fs = require('fs-extra');
const ejs = require('ejs');
async function paste(req, res) {
res.setHeader('Content-Type', 'text/text');
const fileName = this.randomToken(5); // 916,132,832 possible file names
const form = new formidable.IncomingForm();
const protocol = this.protocol();
form.parse(req, (err, fields, files) => {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
if (!this.auth(this.c.key, fields.key, this.c)) {
res.statusCode = 401;
res.write('Unauthorized');
res.end();
return this.log.warning(`Unauthorized User | File Upload | ${userIP}`);
}
this.db.get('files')
.push({
path: `/${fileName}`,
ip: userIP,
views: 0,
})
.write();
const oldpath = files.fdata.path;
const newpath = `${__dirname}/../uploads/${fileName + files.fdata.name.toString().match(/(\.)+([a-zA-Z0-9]+)+/g, '').toString()}`;
if (Math.round((files.fdata.size / 1024) / 1000) > this.c.paste.max_upload_size) {
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[FAILED PASTE][USER]\n[FILE](${files.fdata.name})\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[TYPE](${files.fdata.type})\n[IP](${userIP})\n\n[ERROR](ERR_FILE_TOO_BIG)\`\`\``);
res.statusCode = 413;
res.write(`${protocol}://${req.headers.host}/ERR_FILE_TOO_BIG`);
return res.end();
}
fs.move(oldpath, newpath, () => {
fs.readFile(newpath, 'utf-8', (_err, data) => {
const stream = fs.createWriteStream(`${__dirname}/../uploads/${fileName}.html`);
stream.once('open', () => {
// eslint-disable-next-line no-unused-vars
let cleaned = data.replace(/>/g, '&gt');
cleaned = cleaned.replace(/</g, '&lt');
ejs.renderFile(`${__dirname}/../views/paste.ejs`, {
ogDesc: data.match(/.{1,297}/g)[0],
pData: data,
}, {}, (_renderErr, str) => {
stream.write(str);
});
stream.end();
fs.unlink(newpath, delErr => {
if (delErr) return this.log.warning(delErr);
});
res.write(`${protocol}://${req.headers.host}/${fileName}`);
return res.end();
});
});
});
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[NEW PASTE][USER]\n[SIZE](${Math.round(files.fdata.size / 1024)}KB)\n[IP](${userIP})\n\`\`\`\n${protocol}://${req.headers.host}/${fileName}`);
});
}
module.exports = paste;

24
server/routes/pupload.js Normal file
View File

@ -0,0 +1,24 @@
const fs = require('fs-extra');
async function pupload(req, res) {
res.setHeader('Content-Type', 'text/html');
const givenPassword = req.body.password;
const givenFileName = req.body.file;
const entry = this.db.get('passwordUploads').find({ fileName: givenFileName }).value();
if (entry.key !== givenPassword) {
res.statusCode = 401;
res.render('unauthorized');
return res.end();
}
const filePath = `${__dirname}/../passwordUploads/${entry.fileName}`;
const file = fs.readFileSync(filePath);
if(entry.fileName.includes('.mp3')) {
res.set('Content-Type', 'text/html');
let base64Str = new Buffer(file).toString('base64');
res.render('mp3', { data: base64Str })
} else {
res.set('Content-Type', this.mimeType(entry.fileName));
res.send(file);
}
}
module.exports = pupload;

36
server/routes/short.js Normal file
View File

@ -0,0 +1,36 @@
const fs = require('fs-extra');
async function get(req, res) {
res.setHeader('Content-Type', 'text/html');
res.render('short', { public: this.c.public });
res.end();
}
async function post(req, res) {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
res.setHeader('Content-Type', 'text/text');
if (!this.auth(this.c.key, req.body.password, this.c) && !this.c.public) {
res.statusCode = 401;
res.redirect('/short?error=Incorrect_Password');
res.end();
return this.log.warning(`Unauthorized User | URL Shorten | ${userIP}`);
}
const protocol = this.protocol();
const fileName = this.randomToken(this.c.shortUrlLength);
if (req.body.URL === '' || req.body.URL === null) {
res.redirect('/short?error=No URL Input');
return res.end();
}
const stream = fs.createWriteStream(`${__dirname}/../uploads/${fileName}.html`);
stream.once('open', () => {
stream.write(`<meta http-equiv="refresh" content="0;URL='${req.body.URL}'" />`);
stream.end();
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[NEW][SHORT URL]\n[URL](${req.body.URL})\n[NEW](${req.headers.host}/${fileName})\n[IP](${userIP})\n\`\`\``);
this.log.verbose(`New Short URL: ${protocol}://${req.headers.host}/${fileName} | IP: ${userIP}`);
res.redirect(`/short?success=${protocol}://${req.headers.host}/${fileName}`);
this.db.get('files')
.push({ path: `/${fileName}`, ip: userIP, views: 0 })
.write();
return res.end();
});
}
module.exports = { get, post };

View File

@ -0,0 +1,41 @@
/* eslint-disable no-useless-escape */
const formidable = require('formidable');
const fs = require('fs-extra');
async function shortener(req, res) {
const form = new formidable.IncomingForm();
// eslint-disable-next-line no-unused-vars
form.parse(req, (_err, fields, _files) => {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
const protocol = this.protocol();
if (!this.auth(this.c.key, fields.key, this.c)) {
res.statusCode = 401;
res.write('Unauthorized');
res.end();
return this.log.warning(`Unauthorized User | File Upload | ${userIP}`);
}
const fileName = this.randomToken(4); // 14,776,336 possible file names
const url = req.headers.url;
if (url == null) {
res.send('NO_URL_PROVIDED');
return res.end();
}
if (!/([-a-zA-Z0-9^\p{L}\p{C}\u00a1-\uffff@:%_\+.~#?&//=]{2,256}){1}(\.[a-z]{2,4}){1}(\:[0-9]*)?(\/[-a-zA-Z0-9\u00a1-\uffff\(\)@:%,_\+.~#?&//=]*)?([-a-zA-Z0-9\(\)@:%,_\+.~#?&//=]*)?/.test(url.toLowerCase().toString())) {
res.send('NOT_A_VALID_URL');
return res.end();
}
const stream = fs.createWriteStream(`${__dirname}/../uploads/${fileName}.html`);
stream.once('open', () => {
stream.write(`<meta http-equiv="refresh" content="0; url=${url}" />`);
stream.end();
if (this.monitorChannel !== null) this.bot.createMessage(this.monitorChannel, `\`\`\`MARKDOWN\n[NEW][SHORT URL]\n[URL](${url})\n[NEW](${req.headers.host}/${fileName})\n[IP](${userIP})\n\`\`\``);
this.log.verbose(`New Short URL: ${protocol}://${req.headers.host}/${fileName} | IP: ${userIP}`);
res.write(`${protocol}://${req.headers.host}/${fileName}`);
this.db.get('files')
.push({ path: `/${fileName}`, ip: userIP, views: 0 })
.write();
return res.end();
});
});
}
module.exports = shortener;

6
server/routes/upload.js Normal file
View File

@ -0,0 +1,6 @@
async function upload(_req, res) {
res.setHeader('Content-Type', 'text/html');
res.statusCode = 200;
res.render('upload', { public: this.c.public });
}
module.exports = upload;

BIN
server/uploads/RBTu.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1 @@
button{border-radius:0}button:focus{outline:dotted 1px;outline:-webkit-focus-ring-color auto 5px}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.125rem}.alert-success{color:#496330;background-color:#e8f2df;border-color:#dfedd2}.close{float:right;font-size:1.3125rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}.close:not(:disabled):not(.disabled){cursor:pointer}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.mr-1,.mx-1{margin-right:.3125rem!important}.icon{width:20px;height:20px;vertical-align:middle;display:inline-block;background-size:auto}.fbox3>div[class*=col]{padding-top:5px;padding-bottom:5px}.features-clean{color:#313437;background-color:#fff;padding-bottom:30px}.features-clean p{color:#7d8285}.features-clean h2{font-weight:700;margin-bottom:40px;padding-top:40px;color:inherit}@media (max-width:767px){.features-clean{padding-bottom:10px}.features-clean h2{margin-bottom:25px;padding-top:25px;font-size:24px}}.features-clean .intro{font-size:16px;max-width:500px;margin:0 auto 60px}.features-clean .item{min-height:100px;padding-left:80px;margin-bottom:40px}@media (max-width:767px){.features-clean .intro{margin-bottom:40px}.features-clean .item{min-height:0}}.features-clean .item .name{font-size:20px;font-weight:700;margin-top:0;margin-bottom:20px;color:inherit}.features-clean .item .description{font-size:15px;margin-bottom:0}.features-clean .item .icon{font-size:40px;color:#1485ee;float:left;margin-left:-65px}.form-control.d-xl-flex.justify-content-center.align-items-center.align-content-center.align-self-end.justify-content-lg-center.justify-content-xl-center{text-align:center}.login-clean{background:#f1f7fc;padding:80px 0}.login-clean form{max-width:320px;width:90%;margin:0 auto;background-color:#fff;padding:40px;border-radius:4px;color:#505e6c;box-shadow:1px 1px 5px rgba(0,0,0,.1)}.login-clean .illustration{text-align:center;padding:0 0 20px;font-size:100px;color:#f4476b}.login-clean form .form-control{background:#f7f9fc;border:none;border-bottom:1px solid #dfe7f1;border-radius:0;box-shadow:none;outline:0;color:inherit;text-indent:8px;height:42px}.login-clean form .btn-primary{background:#f4476b;border:none;border-radius:4px;padding:11px;box-shadow:none;margin-top:26px;text-shadow:none;outline:0!important}.login-clean form .btn-primary:active,.login-clean form .btn-primary:hover{background:#eb3b60}.login-clean form .btn-primary:active{transform:translateY(1px)}.login-clean form .forgot{display:block;text-align:center;font-size:12px;color:#6f7a85;opacity:.9;text-decoration:none}.login-clean form .forgot:active,.login-clean form .forgot:hover{opacity:1;text-decoration:none}.navigation-clean{background:#fff;padding-top:.75rem;padding-bottom:.75rem;color:#333;border-radius:0;box-shadow:none;border:none;margin-bottom:0}@media (min-width:768px){.navigation-clean{padding-top:1rem;padding-bottom:1rem}}.navigation-clean .navbar-brand{font-weight:700;color:inherit}.navigation-clean .navbar-brand:hover{color:#222}.navigation-clean .navbar-toggler{border-color:#ddd;color:#888}.navigation-clean .navbar-toggler:focus,.navigation-clean .navbar-toggler:hover{background:0 0}.navigation-clean .form-inline,.navigation-clean .navbar-collapse{border-top-color:#ddd}.navigation-clean.navbar-light .navbar-nav .nav-link.active,.navigation-clean.navbar-light .navbar-nav .nav-link.active:focus,.navigation-clean.navbar-light .navbar-nav .nav-link.active:hover{color:#8f8f8f;box-shadow:none;background:0 0;pointer-events:none}.navigation-clean.navbar .navbar-nav .nav-link{padding-left:18px;padding-right:18px}.navigation-clean.navbar-light .navbar-nav .nav-link{color:#465765}.navigation-clean.navbar-light .navbar-nav .nav-link:focus,.navigation-clean.navbar-light .navbar-nav .nav-link:hover{color:#37434d!important;background-color:transparent}.navigation-clean .navbar-nav>li>.dropdown-menu{margin-top:-5px;box-shadow:none;background-color:#fff;border-radius:2px}.navigation-clean .dropdown-menu .dropdown-item,.navigation-clean .dropdown-menu .dropdown-item:focus{line-height:2;color:#37434d}.navigation-clean .dropdown-menu .dropdown-item:focus,.navigation-clean .dropdown-menu .dropdown-item:hover{background:#eee;color:inherit}.social-icons{color:#313437;background-color:#fff;text-align:center;padding:70px 0}@media (max-width:767px){.social-icons{padding:50px 0}}.social-icons i{font-size:32px;display:inline-block;color:#757980;margin:0 10px;width:60px;height:60px;border:1px solid #c8ced7;text-align:center;border-radius:50%;line-height:60px}

View File

@ -0,0 +1,110 @@
/*
Atom One Dark by Daniel Gamage
Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
base: #282c34
mono-1: #abb2bf
mono-2: #818896
mono-3: #5c6370
hue-1: #56b6c2
hue-2: #61aeee
hue-3: #c678dd
hue-4: #98c379
hue-5: #e06c75
hue-5-2: #be5046
hue-6: #d19a66
hue-6-2: #e6c07b
*/
.hljs {
display: block;
padding: 0.5em;
color: #abb2bf;
background: #282c34;
width: 100%;
height: 100%;
word-wrap: break-word;
}
td.hljs-ln-code {
white-space: pre-wrap;
}
body {
padding: 20px;
}
.hljs-comment,
.hljs-quote {
color: #5c6370;
font-style: italic;
}
.hljs-doctag,
.hljs-keyword,
.hljs-formula {
color: #c678dd;
}
.hljs-section,
.hljs-name,
.hljs-selector-tag,
.hljs-deletion,
.hljs-subst {
color: #e06c75;
}
.hljs-literal {
color: #56b6c2;
}
.hljs-string,
.hljs-regexp,
.hljs-addition,
.hljs-attribute,
.hljs-meta-string {
color: #98c379;
}
.hljs-built_in,
.hljs-class .hljs-title {
color: #e6c07b;
}
.hljs-attr,
.hljs-variable,
.hljs-template-variable,
.hljs-type,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-number {
color: #d19a66;
}
.hljs-symbol,
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-title {
color: #61aeee;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
}
body {
background-color: #282C34;
}

179
server/uploads/css/404.css Normal file
View File

@ -0,0 +1,179 @@
@import url(https://fonts.googleapis.com/css?family=Lato:100,300,400);
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::-webkit-input-placeholder, textarea:focus::-webkit-input-placeholder {
color: #bbb5af;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::-moz-placeholder, textarea:focus::-moz-placeholder {
color: #bbb5af;
}
input::placeholder, textarea::placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::placeholder, textarea::focus:placeholder {
color: #bbb5af;
}
input::-ms-placeholder, textarea::-ms-placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::-ms-placeholder, textarea:focus::-ms-placeholder {
color: #bbb5af;
}
/* on hover placeholder */
input:hover::-webkit-input-placeholder, textarea:hover::-webkit-input-placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::-webkit-input-placeholder, textarea:hover:focus::-webkit-input-placeholder {
color: #cbc6c1;
}
input:hover::-moz-placeholder, textarea:hover::-moz-placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::-moz-placeholder, textarea:hover:focus::-moz-placeholder {
color: #cbc6c1;
}
input:hover::placeholder, textarea:hover::placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::placeholder, textarea:hover:focus::placeholder {
color: #cbc6c1;
}
input:hover::placeholder, textarea:hover::placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::-ms-placeholder, textarea:hover::focus:-ms-placeholder {
color: #cbc6c1;
}
body {
font-family: 'Lato', sans-serif;
background: #e2dedb;
color: #b3aca7;
}
header {
position: relative;
margin: 100px 0 25px 0;
font-size: 2.3em;
text-align: center;
letter-spacing: 7px;
}
return {
position: relative;
margin: 100px 0 25px 0;
font-size: 1.0em;
text-align: center;
letter-spacing: 3px;
}
#form {
position: relative;
width: 500px;
margin: 50px auto 100px auto;
}
input {
font-family: 'Lato', sans-serif;
font-size: 0.875em;
width: 470px;
height: 50px;
padding: 0px 15px 0px 15px;
background: transparent;
outline: none;
color: #726659;
border: solid 1px #b3aca7;
border-bottom: none;
transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
}
input:hover {
background: #b3aca7;
color: #e2dedb;
}
textarea {
width: 470px;
max-width: 470px;
height: 110px;
max-height: 110px;
padding: 15px;
background: transparent;
outline: none;
color: #726659;
font-family: 'Lato', sans-serif;
font-size: 0.875em;
border: solid 1px #b3aca7;
transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
}
textarea:hover {
background: #b3aca7;
color: #e2dedb;
}
#submit {
width: 470px;
padding: 0;
margin: -5px 0px 0px 0px;
font-family: 'Lato', sans-serif;
font-size: 0.875em;
color: #b3aca7;
outline:none;
cursor: pointer;
border: solid 1px #b3aca7;
}
#submit:hover {
color: #e2dedb;
}
a {
color: #726659;
}

BIN
server/uploads/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(n,e){"use strict";function t(){var n=e.createElement("style");n.type="text/css",n.innerHTML=h(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[f,m,j]),e.getElementsByTagName("head")[0].appendChild(n)}function r(t){"complete"===e.readyState?l(t):n.addEventListener("DOMContentLoaded",function(){l(t)})}function l(t){try{var r=e.querySelectorAll("code.hljs");for(var l in r)r.hasOwnProperty(l)&&i(r[l],t)}catch(o){n.console.error("LineNumbers error: ",o)}}function i(n,e){if("object"==typeof n){e=e||{singleLine:!1};var t=e.singleLine?0:1;u(function(){s(n),n.innerHTML=o(n.innerHTML,t)})}}function o(n,e){var t=c(n);if(""===t[t.length-1].trim()&&t.pop(),t.length>e){for(var r="",l=0,i=t.length;l<i;l++)r+=h('<tr><td class="{0}"><div class="{1} {2}" {3}="{5}"></div></td><td class="{4}"><div class="{1}">{6}</div></td></tr>',[v,g,m,j,p,l+1,t[l].length>0?t[l]:" "]);return h('<table class="{0}">{1}</table>',[f,r])}return n}function s(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];d(r.textContent)>0&&(r.childNodes.length>0?s(r):a(r.parentNode))}}function a(n){var e=n.className;if(/hljs-/.test(e)){for(var t=c(n.innerHTML),r=0,l="";r<t.length;r++)l+=h('<span class="{0}">{1}</span>\n',[e,t[r]]);n.innerHTML=l.trim()}}function c(n){return 0===n.length?[]:n.split(L)}function d(n){return(n.trim().match(L)||[]).length}function u(e){n.setTimeout(e,0)}function h(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?e[t]:n})}var f="hljs-ln",g="hljs-ln-line",p="hljs-ln-code",v="hljs-ln-numbers",m="hljs-ln-n",j="data-line-number",L=/\r\n|\r|\n/g;n.hljs?(n.hljs.initLineNumbersOnLoad=r,n.hljs.lineNumbersBlock=i,t()):n.console.error("highlight.js not detected!")}(window,document);

20
server/uploads/paste.css Normal file
View File

@ -0,0 +1,20 @@
::selection {
background: rgba(0, 0, 0, 0.46); /* WebKit/Blink Browsers */
}
::-moz-selection {
background: rgba(0, 0, 0, 0.46); /* Gecko Browsers */
}
td.hljs-ln-numbers {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
color: #414754;
vertical-align: top;
padding-right: 12px !important;
}

239
server/uploads/sample.html Normal file
View File

@ -0,0 +1,239 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="atom-one-dark.css">
<link rel="stylesheet" href="paste.css">
<script src="highlight.pack.js"></script>
</head>
<body>
<pre><code id="code">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Script
{
public class ScriptVariable
{
public object Value { get; set; }
public ScriptTypes Type { get; set; }
public string Name { get; set; }
public ScriptVariable()
{
Value = null;
Type = ScriptTypes.Undefined;
}
public ScriptVariable(object value)
{
Value = value;
Type = value is string ? ScriptTypes.String
: value is int ? ScriptTypes.Integer
: value is double ? ScriptTypes.Double
: value is bool ? ScriptTypes.Boolean
: value is Regex ? ScriptTypes.Regex
: value is List<string> ? ScriptTypes.ListString
: value is List<int> ? ScriptTypes.ListInteger
: value is List<double> ? ScriptTypes.ListDouble
: value is List<bool> ? ScriptTypes.ListBoolean
: ScriptTypes.Null;
}
public ScriptVariable(object value, ScriptTypes type)
{
Value = value;
Type = type;
}
public ScriptVariable(string name, object value)
{
Name = name;
Value = value;
Type = value is string ? ScriptTypes.String
: value is int ? ScriptTypes.Integer
: value is double ? ScriptTypes.Double
: value is bool ? ScriptTypes.Boolean
: value is Regex ? ScriptTypes.Regex
: value is List<string> ? ScriptTypes.ListString
: value is List<int> ? ScriptTypes.ListInteger
: value is List<double> ? ScriptTypes.ListDouble
: value is List<bool> ? ScriptTypes.ListBoolean
: ScriptTypes.Null;
}
public ScriptVariable(string name, object value, ScriptTypes type)
{
Name = name;
Value = value;
Type = type;
}
public T Return<T>()
{
var returnT = ScriptType.ToEnum(typeof(T));
switch (returnT)
{
case ScriptTypes.String:
case ScriptTypes.Integer:
case ScriptTypes.Double:
case ScriptTypes.Boolean:
case ScriptTypes.Regex:
return (T)this.Value;
case ScriptTypes.ListString:
return (T)(object)((List<ScriptVariable>)this.Value).Select(x => x.Value.ToString()).ToList();
case ScriptTypes.ListInteger:
return (T)(object)((List<ScriptVariable>)(this.Value)).Select(x => x).ToList();
case ScriptTypes.ListDouble:
return (T)(object)((List<ScriptVariable>)(this.Value)).Select(x => x).ToList();
case ScriptTypes.ListBoolean:
return (T)(object)((List<ScriptVariable>)(this.Value)).Select(x => x).ToList();
default:
return default(T);
}
}
public ScriptVariable Cast<ReturnT>(Lexer lexer)
{
var outputType = ScriptType.ToEnum(typeof(ReturnT));
switch (outputType)
{
case ScriptTypes.String:
switch (this.Type)
{
case ScriptTypes.Integer:
case ScriptTypes.Double:
this.Value = this.Value.ToString();
break;
case ScriptTypes.Boolean:
this.Value = (bool)this.Value ? "true" : "false";
break;
case ScriptTypes.Null:
this.Value = "null";
break;
}
this.Type = ScriptTypes.String;
break;
case ScriptTypes.Integer:
switch (this.Type)
{
case ScriptTypes.String:
int tryInt = 0;
if (int.TryParse(this.Value.ToString(), out tryInt))
{
this.Value = tryInt;
}
else
{
goto castError;
}
break;
case ScriptTypes.Double:
double tryDouble = 0;
if (double.TryParse(this.Value.ToString(), out tryDouble))
{
this.Value = tryDouble;
}
else
{
goto castError;
}
break;
case ScriptTypes.Boolean:
this.Value = (bool)this.Value ? 1 : 0;
break;
}
this.Type = ScriptTypes.Integer;
break;
case ScriptTypes.Double:
switch (this.Type)
{
case ScriptTypes.String:
case ScriptTypes.Integer:
double tryDouble = 0;
if (double.TryParse(this.Value.ToString(), out tryDouble))
{
this.Value = tryDouble;
}
else
{
goto castError;
}
break;
case ScriptTypes.Boolean:
this.Value = (bool)this.Value ? 1.0 : 0.0;
break;
}
this.Type = ScriptTypes.Double;
break;
case ScriptTypes.Boolean:
switch (this.Type)
{
case ScriptTypes.String:
this.Value = this.Value.ToString() == "true";
break;
}
this.Type = ScriptTypes.Boolean;
break;
case ScriptTypes.ListString:
case ScriptTypes.ListInteger:
case ScriptTypes.ListDouble:
case ScriptTypes.ListBoolean:
break;
case ScriptTypes.Void:
this.Value = default(ReturnT);
break;
}
return this;
castError:
lexer.Prev();
lexer.Prev();
throw new ScriptException(
message: String.Format("Unable to cast value '{0}' from '{1}' to '{2}' on Line {3} Col {4}",
Value.ToString(),
Type.ToString(),
outputType.ToString(),
lexer.LineNumber,
lexer.Position),
row: lexer.LineNumber,
column: lexer.Position,
method: lexer.TokenContents
);
}
/*public ScriptVariable Cast<ReturnT>(Lexer lexer)
{
var outputType = ScriptType.ToEnum(typeof(ReturnT));
var outValue = default(ReturnT);
if (TryCast<ReturnT>(Type, Value, out outValue))
{
return this;
}
lexer.Prev();
lexer.Prev();
throw new ScriptException(
message: String.Format("Unable to cast value '{0}' from '{1}' to '{2}' on Line {3} Col {4}",
Value.ToString(),
Type.ToString(),
outputType.ToString(),
lexer.LineNumber,
lexer.Position),
row: lexer.LineNumber,
column: lexer.Position,
method: lexer.TokenContents
);
}*/
}
}</code></pre>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

BIN
server/uploads/sample.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

39
server/views/404.ejs Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ERROR 404</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/gallery" style="color: rgb(230,94,94);">Gallery</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<h1 class="text-center shadow-none justify-content-center align-items-center align-content-center align-self-center" style="color: rgb(230,94,94);margin: 8px;width: 99%;height: 99%;padding-top: 140px;">404</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ERROR</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/gallery" style="color: rgb(230,94,94);">Gallery</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<h1 class="text-center shadow-none justify-content-center align-items-center align-content-center align-self-center" style="color: rgb(230,94,94);margin: 8px;width: 99%;height: 99%;padding-top: 140px;"><br>The file you uploaded exceeds the file size limit<br></h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>ERROR</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/gallery" style="color: rgb(230,94,94);">Gallery</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<h1 class="text-center shadow-none justify-content-center align-items-center align-content-center align-self-center" style="color: rgb(230,94,94);margin: 8px;width: 99%;height: 99%;padding-top: 140px;"><br>The file type you attempted to upload is not allowed<br></h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1 @@
button{border-radius:0}button:focus{outline:dotted 1px;outline:-webkit-focus-ring-color auto 5px}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.125rem}.alert-success{color:#496330;background-color:#e8f2df;border-color:#dfedd2}.close{float:right;font-size:1.3125rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}.close:not(:disabled):not(.disabled){cursor:pointer}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.mr-1,.mx-1{margin-right:.3125rem!important}.icon{width:20px;height:20px;vertical-align:middle;display:inline-block;background-size:auto}.fbox3>div[class*=col]{padding-top:5px;padding-bottom:5px}.features-clean{color:#313437;background-color:#fff;padding-bottom:30px}.features-clean p{color:#7d8285}.features-clean h2{font-weight:700;margin-bottom:40px;padding-top:40px;color:inherit}@media (max-width:767px){.features-clean{padding-bottom:10px}.features-clean h2{margin-bottom:25px;padding-top:25px;font-size:24px}}.features-clean .intro{font-size:16px;max-width:500px;margin:0 auto 60px}.features-clean .item{min-height:100px;padding-left:80px;margin-bottom:40px}@media (max-width:767px){.features-clean .intro{margin-bottom:40px}.features-clean .item{min-height:0}}.features-clean .item .name{font-size:20px;font-weight:700;margin-top:0;margin-bottom:20px;color:inherit}.features-clean .item .description{font-size:15px;margin-bottom:0}.features-clean .item .icon{font-size:40px;color:#1485ee;float:left;margin-left:-65px}.form-control.d-xl-flex.justify-content-center.align-items-center.align-content-center.align-self-end.justify-content-lg-center.justify-content-xl-center{text-align:center}.login-clean{background:#f1f7fc;padding:80px 0}.login-clean form{max-width:320px;width:90%;margin:0 auto;background-color:#fff;padding:40px;border-radius:4px;color:#505e6c;box-shadow:1px 1px 5px rgba(0,0,0,.1)}.login-clean .illustration{text-align:center;padding:0 0 20px;font-size:100px;color:#f4476b}.login-clean form .form-control{background:#f7f9fc;border:none;border-bottom:1px solid #dfe7f1;border-radius:0;box-shadow:none;outline:0;color:inherit;text-indent:8px;height:42px}.login-clean form .btn-primary{background:#f4476b;border:none;border-radius:4px;padding:11px;box-shadow:none;margin-top:26px;text-shadow:none;outline:0!important}.login-clean form .btn-primary:active,.login-clean form .btn-primary:hover{background:#eb3b60}.login-clean form .btn-primary:active{transform:translateY(1px)}.login-clean form .forgot{display:block;text-align:center;font-size:12px;color:#6f7a85;opacity:.9;text-decoration:none}.login-clean form .forgot:active,.login-clean form .forgot:hover{opacity:1;text-decoration:none}.navigation-clean{background:#fff;padding-top:.75rem;padding-bottom:.75rem;color:#333;border-radius:0;box-shadow:none;border:none;margin-bottom:0}@media (min-width:768px){.navigation-clean{padding-top:1rem;padding-bottom:1rem}}.navigation-clean .navbar-brand{font-weight:700;color:inherit}.navigation-clean .navbar-brand:hover{color:#222}.navigation-clean .navbar-toggler{border-color:#ddd;color:#888}.navigation-clean .navbar-toggler:focus,.navigation-clean .navbar-toggler:hover{background:0 0}.navigation-clean .form-inline,.navigation-clean .navbar-collapse{border-top-color:#ddd}.navigation-clean.navbar-light .navbar-nav .nav-link.active,.navigation-clean.navbar-light .navbar-nav .nav-link.active:focus,.navigation-clean.navbar-light .navbar-nav .nav-link.active:hover{color:#8f8f8f;box-shadow:none;background:0 0;pointer-events:none}.navigation-clean.navbar .navbar-nav .nav-link{padding-left:18px;padding-right:18px}.navigation-clean.navbar-light .navbar-nav .nav-link{color:#465765}.navigation-clean.navbar-light .navbar-nav .nav-link:focus,.navigation-clean.navbar-light .navbar-nav .nav-link:hover{color:#37434d!important;background-color:transparent}.navigation-clean .navbar-nav>li>.dropdown-menu{margin-top:-5px;box-shadow:none;background-color:#fff;border-radius:2px}.navigation-clean .dropdown-menu .dropdown-item,.navigation-clean .dropdown-menu .dropdown-item:focus{line-height:2;color:#37434d}.navigation-clean .dropdown-menu .dropdown-item:focus,.navigation-clean .dropdown-menu .dropdown-item:hover{background:#eee;color:inherit}.social-icons{color:#313437;background-color:#fff;text-align:center;padding:70px 0}@media (max-width:767px){.social-icons{padding:50px 0}}.social-icons i{font-size:32px;display:inline-block;color:#757980;margin:0 10px;width:60px;height:60px;border:1px solid #c8ced7;text-align:center;border-radius:50%;line-height:60px}

179
server/views/css/404.css Normal file
View File

@ -0,0 +1,179 @@
@import url(https://fonts.googleapis.com/css?family=Lato:100,300,400);
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::-webkit-input-placeholder, textarea:focus::-webkit-input-placeholder {
color: #bbb5af;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::-moz-placeholder, textarea:focus::-moz-placeholder {
color: #bbb5af;
}
input::placeholder, textarea::placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::placeholder, textarea::focus:placeholder {
color: #bbb5af;
}
input::-ms-placeholder, textarea::-ms-placeholder {
color: #aca49c;
font-size: 0.875em;
}
input:focus::-ms-placeholder, textarea:focus::-ms-placeholder {
color: #bbb5af;
}
/* on hover placeholder */
input:hover::-webkit-input-placeholder, textarea:hover::-webkit-input-placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::-webkit-input-placeholder, textarea:hover:focus::-webkit-input-placeholder {
color: #cbc6c1;
}
input:hover::-moz-placeholder, textarea:hover::-moz-placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::-moz-placeholder, textarea:hover:focus::-moz-placeholder {
color: #cbc6c1;
}
input:hover::placeholder, textarea:hover::placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::placeholder, textarea:hover:focus::placeholder {
color: #cbc6c1;
}
input:hover::placeholder, textarea:hover::placeholder {
color: #e2dedb;
font-size: 0.875em;
}
input:hover:focus::-ms-placeholder, textarea:hover::focus:-ms-placeholder {
color: #cbc6c1;
}
body {
font-family: 'Lato', sans-serif;
background: #e2dedb;
color: #b3aca7;
}
header {
position: relative;
margin: 100px 0 25px 0;
font-size: 2.3em;
text-align: center;
letter-spacing: 7px;
}
return {
position: relative;
margin: 100px 0 25px 0;
font-size: 1.0em;
text-align: center;
letter-spacing: 3px;
}
#form {
position: relative;
width: 500px;
margin: 50px auto 100px auto;
}
input {
font-family: 'Lato', sans-serif;
font-size: 0.875em;
width: 470px;
height: 50px;
padding: 0px 15px 0px 15px;
background: transparent;
outline: none;
color: #726659;
border: solid 1px #b3aca7;
border-bottom: none;
transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
}
input:hover {
background: #b3aca7;
color: #e2dedb;
}
textarea {
width: 470px;
max-width: 470px;
height: 110px;
max-height: 110px;
padding: 15px;
background: transparent;
outline: none;
color: #726659;
font-family: 'Lato', sans-serif;
font-size: 0.875em;
border: solid 1px #b3aca7;
transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
}
textarea:hover {
background: #b3aca7;
color: #e2dedb;
}
#submit {
width: 470px;
padding: 0;
margin: -5px 0px 0px 0px;
font-family: 'Lato', sans-serif;
font-size: 0.875em;
color: #b3aca7;
outline:none;
cursor: pointer;
border: solid 1px #b3aca7;
}
#submit:hover {
color: #e2dedb;
}
a {
color: #726659;
}

49
server/views/gallery.ejs Normal file
View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Gallery</title>
<meta property="og:site_name" content="ShareX Upload Server">
<meta property="og:title" content="Media Gallery">
<meta property="og:description" content="View Uploaded Media">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<div class="container">
<div class="row fbox3">
<% pictures.forEach(pic => { %>
<div class="col-sm-4 d-flex justify-content-center align-items-center"><a href="<%= pic; %>" data-fancybox="gallery" data-caption="<%= pic; %>"><img class="img-fluid" src="<%= pic; %>" alt="<%= pic; %>"></a></div>
<% })%>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Gallery</title>
<meta property="og:site_name" content="ShareX Upload Server">
<meta property="og:title" content="Media Gallery">
<meta property="og:description" content="View Uploaded Media">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<div class="login-clean" style="background-color: rgb(59,59,59);">
<form action="/gallery" method="post" style="background-color: rgb(51,51,51);">
<h2 class="sr-only">Login Form</h2>
<div class="illustration"><i class="fa fa-photo" style="color: rgb(230,94,94);"></i></div>
<div class="form-group"><input class="form-control" type="password" name="password" placeholder="Password" id="password" style="background-color: rgb(51,51,51);"></div>
<div class="form-group"><button class="btn btn-primary btn-block" type="submit" style="background-color: rgb(230,94,94);">Log In</button></div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.js"></script>
</body>
</html>

23
server/views/md.ejs Normal file
View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta name="theme-color" content="#DC603A">
<meta property="og:title" content="HPaste">
<meta property="og:description" content="<%= ogDesc; %>...">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="highlight.pack.js"></script>
</head>
<style>
body {
margin-top: 30px;
margin-bottom: 30px;
margin-right: 30px;
margin-left: 30px;
}
</style>
<body>
<%- mdRender; %>
<script>hljs.initHighlightingOnLoad()</script>
</body>
</html>

1
server/views/mp3.ejs Normal file
View File

@ -0,0 +1 @@
<body><video controls="" autoplay="" name="media"><source src="data:audio/mp3;base64,<%= data; %>" type="audio/mpeg"></video></body>

17
server/views/paste.ejs Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta name="theme-color" content="#DC603A">
<meta property="og:title" content="HPaste">
<meta property="og:description" content="<%= ogDesc; %>...">
<link rel="stylesheet" href="atom-one-dark.css">
<link rel="stylesheet" href="paste.css">
<script src="highlight.pack.js"></script>
<script src="highlightjs-line-numbers.min.js"></script>
</head>
<body>
<pre><code id="code"><%= pData; %></code></pre>
<script>hljs.initHighlightingOnLoad()</script>
<script>hljs.initLineNumbersOnLoad();</script>
</body>
</html>

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Image Showcase</title>
<meta name="theme-color" content="#DC603A">
<meta property="og:title" content="Image Showcase">
<meta property="og:description" content="Camera: <%= camera; %>
F-Stop: <%= fstop; %>
Shutter Speed: <%= shutter; %>
ISO: <%= iso; %>
Focal Length: <%= focal; %>
Lens: <%= lens; %>">
<meta property="og:image" content="<%= filename; %>">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<style>
.showcaseImage {
filter: drop-shadow(0px 0px 1px rgba(0,0,0,.3))
drop-shadow(0px 0px 10px rgba(0,0,0,.3));
height: <%= height; %>px !important;
width: <%= width; %>px !important;
object-fit: scale-down !important;
}
body {
background-color: white;
height: 100%;
}
.is-horizontal-center {
justify-content: center;
display: inline;
}
</style>
</head>
<body>
<section class="section has-text-centered ">
<div class="has-text-centered">
<h4><%= dims; %></h4>
<br />
<a class="column is-one-quarter is-horizontal-center has-text-centered "data-fancybox="gallery" data-caption="<b>Camera:</b> <%= camera; %><br />
<b>F-Stop:</b> <%= fstop; %><br />
<b>Shutter Speed:</b> <%= shutter; %><br />
<b>ISO:</b> <%= iso; %><br />
<b>Lens:</b> <%= lens; %><br />
<b>Focal Length:</b> <%= focal; %>" href="<%= filename; %>"><img height="500px" class="is-horizontal-center showcaseImage" src="<%= filename; %>"></a>
</div>
</section>
</body>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Authorization</title>
<meta property="og:site_name" content="ShareX Upload Server">
<meta property="og:title" content="Password Protected Media">
<meta property="og:description" content="Provide password to view contents">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div class="login-clean" style="background-color: rgb(59,59,59);">
<form action="/pupload" method="post" style="background-color: rgb(51,51,51);">
<h2 class="sr-only">Login Form</h2>
<div class="illustration"><i class="fa fa-photo" style="color: rgb(230,94,94);"></i></div>
<div class="form-group"><input class="form-control" type="password" name="password" placeholder="Password" id="password" style="background-color: rgb(51,51,51);"></div>
<div class="form-group"><input class="form-control" type="email" name="file" value="<%= fileName; %>" id="file" style="background-color: rgb(51,51,51);" readonly></div>
<div class="form-group"><button class="btn btn-primary btn-block" type="submit" style="background-color: rgb(230,94,94);">Authorize</button></div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.js"></script>
</body>
</html>

77
server/views/short.ejs Normal file
View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>URL Shortener</title>
<meta property="og:site_name" content="ShareX Upload Server">
<meta property="og:title" content="URL Shortener">
<meta property="og:description" content="Shorten a URL">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
<style>
.err::-webkit-input-placeholder {
color: red;
}
.success::-webkit-input-placeholder {
color: green;
}
</style>
</head>
<body style="background-color: rgb(59,59,59);">
<div id="afterBox">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
if(window.location.search){
if(window.location.search.toString().includes("error")){
var error = window.location.search.toString().replace(/(\?error=)+/g, '').replace(/[\_]/g, ' ');
document.getElementById("afterBox").innerHTML = '<div class="alert alert-info" role="alert" id="save-sucess" style="height: 50px;padding-bottom: 6px;margin-bottom: 0px;"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button><i class="icon ion-checkmark-round mr-1"></i><span style="color: #0C6D38 !important;">'+ error + '<br></span></div>';
}else{
var result = window.location.search.toString().replace(/(\?success=)+/g, '').replace(/[\_]/g, ' ');
document.getElementById("afterBox").innerHTML = '<div class="alert alert-info" role="alert" id="save-sucess" style="background-color: #B4F7D2!important;border: 1px solid #0C6D38;height: 50px;padding-bottom: 6px;margin-bottom: 0px;"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button><i class="icon ion-checkmark-round mr-1"></i><span style="color: #0C6D38 !important;">'+ result + '<br></span></div>';
}
}
});
</script>
</div>
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/gallery" style="color: rgb(230,94,94);">Gallery</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<div class="login-clean" style="background-color: rgb(59,59,59);">
<form action="/short" method="post" id="urlForm" style="background-color: rgb(52,52,52);">
<h2 class="sr-only">Login Form</h2>
<div class="illustration"><i class="fas fa-link" style="color: rgb(230,94,94);"></i></div>
<div class="form-group"><input type="url" id="URL" name="URL" placeholder="URL" autocomplete="off" inputmode="url" class="form-control" style="background-color: rgb(52,52,52);" /></div>
<% if(!public) { %>
<div class="form-group"><input class="form-control" type="password" name="password" placeholder="Password" id="password" style="background-color: rgb(51,51,51);"></div>
<% } %>
<div class="form-group"><button class="btn btn-primary btn-block" type="submit" style="background-color: rgb(230,94,94);">Shorten URL</button></div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>UNAUTHORIZED</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/gallery" style="color: rgb(230,94,94);">Gallery</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/upload" style="color: rgb(230,94,94);">Upload</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<h1 class="text-center shadow-none justify-content-center align-items-center align-content-center align-self-center" style="color: rgb(230,94,94);margin: 8px;width: 99%;height: 99%;padding-top: 140px;"><br>UNAUTHORIZED<br></h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

71
server/views/upload.ejs Normal file
View File

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Upload</title>
<meta property="og:site_name" content="ShareX Upload Server">
<meta property="og:title" content="File Upload">
<meta property="og:description" content="Upload files to the server">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=ABeeZee">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.css">
<link rel="stylesheet" href="assets/css/styles.min.css">
</head>
<body style="background-color: rgb(59,59,59);">
<div id="afterBox">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
if(window.location.search){
if(window.location.search.toString().includes("error")){
var error = window.location.search.toString().replace(/(\?error=)+/g, '').replace(/[\_]/g, ' ');
document.getElementById("afterBox").innerHTML = '<div class="alert alert-info" role="alert" id="save-sucess" style="height: 50px;padding-bottom: 6px;margin-bottom: 0px;"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button><i class="icon ion-checkmark-round mr-1"></i><span style="color: #0C6D38 !important;">'+ error + '<br></span></div>';
}else{
var result = window.location.search.toString().replace(/(\?success=)+/g, '').replace(/[\_]/g, ' ');
document.getElementById("afterBox").innerHTML = '<div class="alert alert-info" role="alert" id="save-sucess" style="background-color: #B4F7D2!important;border: 1px solid #0C6D38;height: 50px;padding-bottom: 6px;margin-bottom: 0px;"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button><i class="icon ion-checkmark-round mr-1"></i><span style="color: #0C6D38 !important;">'+ result + '<br></span></div>';
}
}
});
</script>
</div>
<div>
<nav class="navbar navbar-light navbar-expand-md navigation-clean" style="background-color: rgb(52,52,52);">
<div class="container"><a class="navbar-brand text-left d-flex d-xl-flex justify-content-xl-start" href="#" style="color: rgb(255,255,255);font-family: Roboto, sans-serif;">ShareX Webserver</a><button class="navbar-toggler" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div
class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" role="presentation"><a class="nav-link" href="/" style="color: rgb(230,94,94);">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/short" style="color: rgb(230,94,94);">URL Shortener</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="/gallery" style="color: rgb(230,94,94);">Gallery</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" href="https://github.com/TannerReynolds/node-sharex-server" style="color: rgb(230,94,94);">Github</a></li>
</ul>
</div>
</div>
</nav>
</div>
<div class="login-clean" style="background-color: rgb(59,59,59);">
<form action="/api/files" method="post" style="background-color: rgb(51,51,51);" enctype="multipart/form-data" name="fdataForm">
<h2 class="sr-only">Upload Form</h2>
<div class="illustration"><i class="fa fa-photo" style="color: rgb(230,94,94);"></i></div>
<% if(!public) { %>
<div class="form-group"><input class="form-control" type="password" name="password" placeholder="Password" id="password" style="background-color: rgb(51,51,51);"></div>
<% } %>
<div class="form-group"><input class="form-control" type="password" name="pupload" placeholder="Pupload" id="pupload" style="background-color: rgb(51,51,51);"></div>
<div class = "form-group"><input type="file" id="fdataUploader" name="fdataUploader" required/></div>
<div class="form-group"><button class="btn btn-primary btn-block" type="submit" style="background-color: rgb(230,94,94);">Upload</button></div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.2/dist/jquery.fancybox.min.js"></script>
</body>
</html>

5
util/auth.js Normal file
View File

@ -0,0 +1,5 @@
function auth(myKey, givenKey, c) {
if (c.key.includes(givenKey) || c.admin.key.includes(givenKey) || c.public === true || myKey === null) return true;
return false;
}
module.exports = auth;

6
util/index.js Normal file
View File

@ -0,0 +1,6 @@
require('fs')
.readdirSync(__dirname)
.map(filename => {
const moduleName = filename.split('.')[0];
exports[moduleName] = require(`${__dirname}/${filename}`);
});

55
util/log.js Normal file
View File

@ -0,0 +1,55 @@
/* eslint-disable no-console */
/** Colors to display in terminal */
const fg = {
black: '\x1b[30m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m',
white: '\x1b[37m',
};
const bg = {
black: '\x1b[40m',
red: '\x1b[41m',
green: '\x1b[42m',
yellow: '\x1b[43m',
blue: '\x1b[44m',
magenta: '\x1b[45m',
cyan: '\x1b[46m',
white: '\x1b[47m',
};
const endColor = '\x1b[0m';
/**
* Timestamp generation
* @returns {string} [11:05:49 PM]
*/
function timestamp() {
const time = new Date();
return time.toLocaleString('en-US', {
hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: true,
});
}
/**
* Logs to console with proper styling and a timestamp
* @param {string} log - string you want to log
* @returns {Promise}
*/
function uncaughtError(log) {
console.log(`${fg.red} |> ${endColor}${bg.red}[${timestamp()}]${endColor}${fg.red} | ${log}${endColor}`);
}
function success(log) {
console.log(`${fg.red} |> ${endColor}${bg.green}[${timestamp()}]${endColor}${fg.green} | ${log}${endColor}`);
}
function warning(log) {
console.log(`${fg.red} |> ${endColor}${bg.magenta}[${timestamp()}]${endColor}${fg.magenta} | ${log}${endColor}`);
}
function verbose(log) {
console.log(`${fg.red} |> ${endColor}${bg.blue}[${timestamp()}]${endColor}${fg.blue} | ${log}${endColor}`);
}
module.exports = {
uncaughtError, success, warning, verbose,
};

656
util/mimeType.js Normal file
View File

@ -0,0 +1,656 @@
/* eslint-disable no-dupe-keys */
/**
* Takes a file extension and returns it's MIME type
* @param {string} fileName - file name including extension (example.pdf)
* @returns {string} MIME Type
*/
function mimeType(fileName) {
const mimeTypes = {
'.3dm': 'x-world/x-3dmf',
'.3dmf': 'x-world/x-3dmf',
'.a': 'application/octet-stream',
'.aab': 'application/x-authorware-bin',
'.aam': 'application/x-authorware-map',
'.aas': 'application/x-authorware-seg',
'.abc': 'text/vnd.abc',
'.acgi': 'text/html',
'.afl': 'video/animaflex',
'.ai': 'application/postscript',
'.aif': 'audio/aiff',
'.aif': 'audio/x-aiff',
'.aifc': 'audio/aiff',
'.aifc': 'audio/x-aiff',
'.aiff': 'audio/aiff',
'.aiff': 'audio/x-aiff',
'.aim': 'application/x-aim',
'.aip': 'text/x-audiosoft-intra',
'.ani': 'application/x-navi-animation',
'.aos': 'application/x-nokia-9000-communicator-add-on-software',
'.aps': 'application/mime',
'.arc': 'application/octet-stream',
'.arj': 'application/arj',
'.arj': 'application/octet-stream',
'.art': 'image/x-jg',
'.asf': 'video/x-ms-asf',
'.asm': 'text/x-asm',
'.asp': 'text/asp',
'.asx': 'application/x-mplayer2',
'.asx': 'video/x-ms-asf',
'.asx': 'video/x-ms-asf-plugin',
'.au': 'audio/basic',
'.au': 'audio/x-au',
'.avi': 'application/x-troff-msvideo',
'.avi': 'video/avi',
'.avi': 'video/msvideo',
'.avi': 'video/x-msvideo',
'.avs': 'video/avs-video',
'.bcpio': 'application/x-bcpio',
'.bin': 'application/mac-binary',
'.bin': 'application/macbinary',
'.bin': 'application/octet-stream',
'.bin': 'application/x-binary',
'.bin': 'application/x-macbinary',
'.bm': 'image/bmp',
'.bmp': 'image/bmp',
'.bmp': 'image/x-windows-bmp',
'.boo': 'application/book',
'.book': 'application/book',
'.boz': 'application/x-bzip2',
'.bsh': 'application/x-bsh',
'.bz': 'application/x-bzip',
'.bz2': 'application/x-bzip2',
'.c': 'text/plain',
'.c': 'text/x-c',
'.c++': 'text/plain',
'.cat': 'application/vnd.ms-pki.seccat',
'.cc': 'text/plain',
'.cc': 'text/x-c',
'.ccad': 'application/clariscad',
'.cco': 'application/x-cocoa',
'.cdf': 'application/cdf',
'.cdf': 'application/x-cdf',
'.cdf': 'application/x-netcdf',
'.cer': 'application/pkix-cert',
'.cer': 'application/x-x509-ca-cert',
'.cha': 'application/x-chat',
'.chat': 'application/x-chat',
'.class': 'application/java',
'.class': 'application/java-byte-code',
'.class': 'application/x-java-class',
'.com': 'application/octet-stream',
'.com': 'text/plain',
'.conf': 'text/plain',
'.cpio': 'application/x-cpio',
'.cpp': 'text/x-c',
'.cpt': 'application/mac-compactpro',
'.cpt': 'application/x-compactpro',
'.cpt': 'application/x-cpt',
'.crl': 'application/pkcs-crl',
'.crl': 'application/pkix-crl',
'.crt': 'application/pkix-cert',
'.crt': 'application/x-x509-ca-cert',
'.crt': 'application/x-x509-user-cert',
'.csh': 'application/x-csh',
'.csh': 'text/x-script.csh',
'.css': 'application/x-pointplus',
'.css': 'text/css',
'.cxx': 'text/plain',
'.dcr': 'application/x-director',
'.deepv': 'application/x-deepv',
'.def': 'text/plain',
'.der': 'application/x-x509-ca-cert',
'.dif': 'video/x-dv',
'.dir': 'application/x-director',
'.dl': 'video/dl',
'.dl': 'video/x-dl',
'.doc': 'application/msword',
'.dot': 'application/msword',
'.dp': 'application/commonground',
'.drw': 'application/drafting',
'.dump': 'application/octet-stream',
'.dv': 'video/x-dv',
'.dvi': 'application/x-dvi',
'.dwf': 'drawing/x-dwf',
'.dwf': 'model/vnd.dwf',
'.dwg': 'application/acad',
'.dwg': 'image/vnd.dwg',
'.dwg': 'image/x-dwg',
'.dxf': 'application/dxf',
'.dxf': 'image/vnd.dwg',
'.dxf': 'image/x-dwg',
'.dxr': 'application/x-director',
'.el': 'text/x-script.elisp',
'.elc': 'application/x-bytecode.elisp',
'.elc': 'application/x-elc',
'.env': 'application/x-envoy',
'.eps': 'application/postscript',
'.es': 'application/x-esrehber',
'.etx': 'text/x-setext',
'.evy': 'application/envoy',
'.evy': 'application/x-envoy',
'.exe': 'application/octet-stream',
'.f': 'text/plain',
'.f': 'text/x-fortran',
'.f77': 'text/x-fortran',
'.f90': 'text/plain',
'.f90': 'text/x-fortran',
'.fdf': 'application/vnd.fdf',
'.fif': 'application/fractals',
'.fif': 'image/fif',
'.fli': 'video/fli',
'.fli': 'video/x-fli',
'.flo': 'image/florian',
'.flx': 'text/vnd.fmi.flexstor',
'.fmf': 'video/x-atomic3d-feature',
'.for': 'text/plain',
'.for': 'text/x-fortran',
'.fpx': 'image/vnd.fpx',
'.fpx': 'image/vnd.net-fpx',
'.frl': 'application/freeloader',
'.funk': 'audio/make',
'.g': 'text/plain',
'.g3': 'image/g3fax',
'.gif': 'image/gif',
'.gl': 'video/gl',
'.gl': 'video/x-gl',
'.gsd': 'audio/x-gsm',
'.gsm': 'audio/x-gsm',
'.gsp': 'application/x-gsp',
'.gss': 'application/x-gss',
'.gtar': 'application/x-gtar',
'.gz': 'application/x-compressed',
'.gz': 'application/x-gzip',
'.gzip': 'application/x-gzip',
'.gzip': 'multipart/x-gzip',
'.h': 'text/plain',
'.h': 'text/x-h',
'.hdf': 'application/x-hdf',
'.help': 'application/x-helpfile',
'.hgl': 'application/vnd.hp-hpgl',
'.hh': 'text/plain',
'.hh': 'text/x-h',
'.hlb': 'text/x-script',
'.hlp': 'application/hlp',
'.hlp': 'application/x-helpfile',
'.hlp': 'application/x-winhelp',
'.hpg': 'application/vnd.hp-hpgl',
'.hpgl': 'application/vnd.hp-hpgl',
'.hqx': 'application/binhex',
'.hqx': 'application/binhex4',
'.hqx': 'application/mac-binhex',
'.hqx': 'application/mac-binhex40',
'.hqx': 'application/x-binhex40',
'.hqx': 'application/x-mac-binhex40',
'.hta': 'application/hta',
'.htc': 'text/x-component',
'.htm': 'text/html',
'.html': 'text/html',
'.htmls': 'text/html',
'.htt': 'text/webviewhtml',
'.htx': 'text/html',
'.ice': 'x-conference/x-cooltalk',
'.ico': 'image/x-icon',
'.idc': 'text/plain',
'.ief': 'image/ief',
'.iefs': 'image/ief',
'.iges': 'application/iges',
'.iges': 'model/iges',
'.igs': 'application/iges',
'.igs': 'model/iges',
'.ima': 'application/x-ima',
'.imap': 'application/x-httpd-imap',
'.inf': 'application/inf',
'.ins': 'application/x-internett-signup',
'.ip': 'application/x-ip2',
'.isu': 'video/x-isvideo',
'.it': 'audio/it',
'.iv': 'application/x-inventor',
'.ivr': 'i-world/i-vrml',
'.ivy': 'application/x-livescreen',
'.jam': 'audio/x-jam',
'.jav': 'text/plain',
'.jav': 'text/x-java-source',
'.java': 'text/plain',
'.java': 'text/x-java-source',
'.jcm': 'application/x-java-commerce',
'.jfif': 'image/jpeg',
'.jfif-tbnl': 'image/jpeg',
'.jpe': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.jpg': 'image/jpeg',
'.jps': 'image/x-jps',
'.js': 'application/x-javascript',
'.jut': 'image/jutvision',
'.kar': 'audio/midi',
'.kar': 'music/x-karaoke',
'.ksh': 'application/x-ksh',
'.ksh': 'text/x-script.ksh',
'.la': 'audio/nspaudio',
'.la': 'audio/x-nspaudio',
'.lam': 'audio/x-liveaudio',
'.latex': 'application/x-latex',
'.lha': 'application/lha',
'.lha': 'application/octet-stream',
'.lha': 'application/x-lha',
'.lhx': 'application/octet-stream',
'.list': 'text/plain',
'.lma': 'audio/nspaudio',
'.lma': 'audio/x-nspaudio',
'.log': 'text/plain',
'.lsp': 'application/x-lisp',
'.lsp': 'text/x-script.lisp',
'.lst': 'text/plain',
'.lsx': 'text/x-la-asf',
'.ltx': 'application/x-latex',
'.lzh': 'application/octet-stream',
'.lzh': 'application/x-lzh',
'.lzx': 'application/lzx',
'.lzx': 'application/octet-stream',
'.lzx': 'application/x-lzx',
'.m': 'text/plain',
'.m': 'text/x-m',
'.m1v': 'video/mpeg',
'.m2a': 'audio/mpeg',
'.m2v': 'video/mpeg',
'.m3u': 'audio/x-mpequrl',
'.man': 'application/x-troff-man',
'.map': 'application/x-navimap',
'.mar': 'text/plain',
'.mbd': 'application/mbedlet',
'.mc$': 'application/x-magic-cap-package-1.0',
'.mcd': 'application/mcad',
'.mcd': 'application/x-mathcad',
'.mcf': 'image/vasa',
'.mcf': 'text/mcf',
'.mcp': 'application/netmc',
'.me': 'application/x-troff-me',
'.mht': 'message/rfc822',
'.mhtml': 'message/rfc822',
'.mid': 'application/x-midi',
'.mid': 'audio/midi',
'.mid': 'audio/x-mid',
'.mid': 'audio/x-midi',
'.mid': 'music/crescendo',
'.mid': 'x-music/x-midi',
'.midi': 'application/x-midi',
'.midi': 'audio/midi',
'.midi': 'audio/x-mid',
'.midi': 'audio/x-midi',
'.midi': 'music/crescendo',
'.midi': 'x-music/x-midi',
'.mif': 'application/x-frame',
'.mif': 'application/x-mif',
'.mime': 'message/rfc822',
'.mime': 'www/mime',
'.mjf': 'audio/x-vnd.audioexplosion.mjuicemediafile',
'.mjpg': 'video/x-motion-jpeg',
'.mm': 'application/base64',
'.mm': 'application/x-meme',
'.mme': 'application/base64',
'.mod': 'audio/mod',
'.mod': 'audio/x-mod',
'.moov': 'video/quicktime',
'.mov': 'video/quicktime',
'.movie': 'video/x-sgi-movie',
'.mp2': 'audio/mpeg',
'.mp2': 'audio/x-mpeg',
'.mp2': 'video/mpeg',
'.mp2': 'video/x-mpeg',
'.mp2': 'video/x-mpeq2a',
'.mp3': 'audio/mpeg3',
'.mp3': 'audio/x-mpeg-3',
'.mp3': 'video/mpeg',
'.mp3': 'video/x-mpeg',
'.mpa': 'audio/mpeg',
'.mpa': 'video/mpeg',
'.mpc': 'application/x-project',
'.mpe': 'video/mpeg',
'.mpeg': 'video/mpeg',
'.mpg': 'audio/mpeg',
'.mpg': 'video/mpeg',
'.mpga': 'audio/mpeg',
'.mpp': 'application/vnd.ms-project',
'.mpt': 'application/x-project',
'.mpv': 'application/x-project',
'.mpx': 'application/x-project',
'.mrc': 'application/marc',
'.ms': 'application/x-troff-ms',
'.mv': 'video/x-sgi-movie',
'.my': 'audio/make',
'.mzz': 'application/x-vnd.audioexplosion.mzz',
'.nap': 'image/naplps',
'.naplps': 'image/naplps',
'.nc': 'application/x-netcdf',
'.ncm': 'application/vnd.nokia.configuration-message',
'.nif': 'image/x-niff',
'.niff': 'image/x-niff',
'.nix': 'application/x-mix-transfer',
'.nsc': 'application/x-conference',
'.nvd': 'application/x-navidoc',
'.o': 'application/octet-stream',
'.oda': 'application/oda',
'.omc': 'application/x-omc',
'.omcd': 'application/x-omcdatamaker',
'.omcr': 'application/x-omcregerator',
'.p': 'text/x-pascal',
'.p10': 'application/pkcs10',
'.p10': 'application/x-pkcs10',
'.p12': 'application/pkcs-12',
'.p12': 'application/x-pkcs12',
'.p7a': 'application/x-pkcs7-signature',
'.p7c': 'application/pkcs7-mime',
'.p7c': 'application/x-pkcs7-mime',
'.p7m': 'application/pkcs7-mime',
'.p7m': 'application/x-pkcs7-mime',
'.p7r': 'application/x-pkcs7-certreqresp',
'.p7s': 'application/pkcs7-signature',
'.part': 'application/pro_eng',
'.pas': 'text/pascal',
'.pbm': 'image/x-portable-bitmap',
'.pcl': 'application/vnd.hp-pcl',
'.pcl': 'application/x-pcl',
'.pct': 'image/x-pict',
'.pcx': 'image/x-pcx',
'.pdb': 'chemical/x-pdb',
'.pdf': 'application/pdf',
'.pfunk': 'audio/make',
'.pfunk': 'audio/make.my.funk',
'.pgm': 'image/x-portable-graymap',
'.pgm': 'image/x-portable-greymap',
'.pic': 'image/pict',
'.pict': 'image/pict',
'.pkg': 'application/x-newton-compatible-pkg',
'.pko': 'application/vnd.ms-pki.pko',
'.pl': 'text/plain',
'.pl': 'text/x-script.perl',
'.plx': 'application/x-pixclscript',
'.pm': 'image/x-xpixmap',
'.pm': 'text/x-script.perl-module',
'.pm4': 'application/x-pagemaker',
'.pm5': 'application/x-pagemaker',
'.png': 'image/png',
'.pnm': 'application/x-portable-anymap',
'.pnm': 'image/x-portable-anymap',
'.pot': 'application/mspowerpoint',
'.pot': 'application/vnd.ms-powerpoint',
'.pov': 'model/x-pov',
'.ppa': 'application/vnd.ms-powerpoint',
'.ppm': 'image/x-portable-pixmap',
'.pps': 'application/mspowerpoint',
'.pps': 'application/vnd.ms-powerpoint',
'.ppt': 'application/mspowerpoint',
'.ppt': 'application/powerpoint',
'.ppt': 'application/vnd.ms-powerpoint',
'.ppt': 'application/x-mspowerpoint',
'.ppz': 'application/mspowerpoint',
'.pre': 'application/x-freelance',
'.prt': 'application/pro_eng',
'.ps': 'application/postscript',
'.psd': 'application/octet-stream',
'.pvu': 'paleovu/x-pv',
'.pwz': 'application/vnd.ms-powerpoint',
'.py': 'text/x-script.phyton',
'.pyc': 'applicaiton/x-bytecode.python',
'.qcp': 'audio/vnd.qcelp',
'.qd3': 'x-world/x-3dmf',
'.qd3d': 'x-world/x-3dmf',
'.qif': 'image/x-quicktime',
'.qt': 'video/quicktime',
'.qtc': 'video/x-qtc',
'.qti': 'image/x-quicktime',
'.qtif': 'image/x-quicktime',
'.ra': 'audio/x-pn-realaudio',
'.ra': 'audio/x-pn-realaudio-plugin',
'.ra': 'audio/x-realaudio',
'.ram': 'audio/x-pn-realaudio',
'.ras': 'application/x-cmu-raster',
'.ras': 'image/cmu-raster',
'.ras': 'image/x-cmu-raster',
'.rast': 'image/cmu-raster',
'.rexx': 'text/x-script.rexx',
'.rf': 'image/vnd.rn-realflash',
'.rgb': 'image/x-rgb',
'.rm': 'application/vnd.rn-realmedia',
'.rm': 'audio/x-pn-realaudio',
'.rmi': 'audio/mid',
'.rmm': 'audio/x-pn-realaudio',
'.rmp': 'audio/x-pn-realaudio',
'.rmp': 'audio/x-pn-realaudio-plugin',
'.rng': 'application/ringing-tones',
'.rng': 'application/vnd.nokia.ringing-tone',
'.rnx': 'application/vnd.rn-realplayer',
'.roff': 'application/x-troff',
'.rp': 'image/vnd.rn-realpix',
'.rpm': 'audio/x-pn-realaudio-plugin',
'.rt': 'text/richtext',
'.rt': 'text/vnd.rn-realtext',
'.rtf': 'application/rtf',
'.rtf': 'application/x-rtf',
'.rtf': 'text/richtext',
'.rtx': 'application/rtf',
'.rtx': 'text/richtext',
'.rv': 'video/vnd.rn-realvideo',
'.s': 'text/x-asm',
'.s3m': 'audio/s3m',
'.saveme': 'application/octet-stream',
'.sbk': 'application/x-tbook',
'.scm': 'application/x-lotusscreencam',
'.scm': 'text/x-script.guile',
'.scm': 'text/x-script.scheme',
'.scm': 'video/x-scm',
'.sdml': 'text/plain',
'.sdp': 'application/sdp',
'.sdp': 'application/x-sdp',
'.sdr': 'application/sounder',
'.sea': 'application/sea',
'.sea': 'application/x-sea',
'.set': 'application/set',
'.sgm': 'text/sgml',
'.sgm': 'text/x-sgml',
'.sgml': 'text/sgml',
'.sgml': 'text/x-sgml',
'.sh': 'application/x-bsh',
'.sh': 'application/x-sh',
'.sh': 'application/x-shar',
'.sh': 'text/x-script.sh',
'.shar': 'application/x-bsh',
'.shar': 'application/x-shar',
'.shtml': 'text/html',
'.shtml': 'text/x-server-parsed-html',
'.sid': 'audio/x-psid',
'.sit': 'application/x-sit',
'.sit': 'application/x-stuffit',
'.skd': 'application/x-koan',
'.skm': 'application/x-koan',
'.skp': 'application/x-koan',
'.skt': 'application/x-koan',
'.sl': 'application/x-seelogo',
'.smi': 'application/smil',
'.smil': 'application/smil',
'.snd': 'audio/basic',
'.snd': 'audio/x-adpcm',
'.sol': 'application/solids',
'.spc': 'application/x-pkcs7-certificates',
'.spc': 'text/x-speech',
'.spl': 'application/futuresplash',
'.spr': 'application/x-sprite',
'.sprite': 'application/x-sprite',
'.src': 'application/x-wais-source',
'.ssi': 'text/x-server-parsed-html',
'.ssm': 'application/streamingmedia',
'.sst': 'application/vnd.ms-pki.certstore',
'.step': 'application/step',
'.stl': 'application/sla',
'.stl': 'application/vnd.ms-pki.stl',
'.stl': 'application/x-navistyle',
'.stp': 'application/step',
'.sv4cpio': 'application/x-sv4cpio',
'.sv4crc': 'application/x-sv4crc',
'.svf': 'image/vnd.dwg',
'.svf': 'image/x-dwg',
'.svr': 'application/x-world',
'.svr': 'x-world/x-svr',
'.swf': 'application/x-shockwave-flash',
'.t': 'application/x-troff',
'.talk': 'text/x-speech',
'.tar': 'application/x-tar',
'.tbk': 'application/toolbook',
'.tbk': 'application/x-tbook',
'.tcl': 'application/x-tcl',
'.tcl': 'text/x-script.tcl',
'.tcsh': 'text/x-script.tcsh',
'.tex': 'application/x-tex',
'.texi': 'application/x-texinfo',
'.texinfo': 'application/x-texinfo',
'.text': 'application/plain',
'.text': 'text/plain',
'.tgz': 'application/gnutar',
'.tgz': 'application/x-compressed',
'.tif': 'image/tiff',
'.tif': 'image/x-tiff',
'.tiff': 'image/tiff',
'.tiff': 'image/x-tiff',
'.tr': 'application/x-troff',
'.tsi': 'audio/tsp-audio',
'.tsp': 'application/dsptype',
'.tsp': 'audio/tsplayer',
'.tsv': 'text/tab-separated-values',
'.turbot': 'image/florian',
'.txt': 'text/plain',
'.uil': 'text/x-uil',
'.uni': 'text/uri-list',
'.unis': 'text/uri-list',
'.unv': 'application/i-deas',
'.uri': 'text/uri-list',
'.uris': 'text/uri-list',
'.ustar': 'application/x-ustar',
'.ustar': 'multipart/x-ustar',
'.uu': 'application/octet-stream',
'.uu': 'text/x-uuencode',
'.uue': 'text/x-uuencode',
'.vcd': 'application/x-cdlink',
'.vcs': 'text/x-vcalendar',
'.vda': 'application/vda',
'.vdo': 'video/vdo',
'.vew': 'application/groupwise',
'.viv': 'video/vivo',
'.viv': 'video/vnd.vivov',
'.vivo': 'video/vivo',
'.vivo': 'video/vnd.vivo',
'.vmd': 'application/vocaltec-media-desc',
'.vmf': 'application/vocaltec-media-file',
'.voc': 'audio/voc',
'.voc': 'audio/x-voc',
'.vos': 'video/vosaic',
'.vox': 'audio/voxware',
'.vqe': 'audio/x-twinvq-plugin',
'.vqf': 'audio/x-twinvq',
'.vql': 'audio/x-twinvq-plugin',
'.vrml': 'application/x-vrml',
'.vrml': 'model/vrml',
'.vrml': 'x-world/x-vrml',
'.vrt': 'x-world/x-vrt',
'.vsd': 'application/x-visio',
'.vst': 'application/x-visio',
'.vsw': 'application/x-visio',
'.w60': 'application/wordperfect6.0',
'.w61': 'application/wordperfect6.1',
'.w6w': 'application/msword',
'.wav': 'audio/wav',
'.wav': 'audio/x-wav',
'.wb1': 'application/x-qpro',
'.wbmp': 'image/vnd.wap.wbmp',
'.web': 'application/vnd.xara',
'.wiz': 'application/msword',
'.wk1': 'application/x-123',
'.wmf': 'windows/metafile',
'.wml': 'text/vnd.wap.wml',
'.wmlc': 'application/vnd.wap.wmlc',
'.wmls': 'text/vnd.wap.wmlscript',
'.wmlsc': 'application/vnd.wap.wmlscriptc',
'.word': 'application/msword',
'.wp': 'application/wordperfect',
'.wp5': 'application/wordperfect',
'.wp5': 'application/wordperfect6.0',
'.wp6': 'application/wordperfect',
'.wpd': 'application/wordperfect',
'.wpd': 'application/x-wpwin',
'.wq1': 'application/x-lotus',
'.wri': 'application/mswrite',
'.wri': 'application/x-wri',
'.wrl': 'application/x-world',
'.wrl': 'model/vrml',
'.wrl': 'x-world/x-vrml',
'.wrz': 'model/vrml',
'.wrz': 'x-world/x-vrml',
'.wsc': 'text/scriplet',
'.wsrc': 'application/x-wais-source',
'.wtk': 'application/x-wintalk',
'.xbm': 'image/x-xbitmap',
'.xbm': 'image/x-xbm',
'.xbm': 'image/xbm',
'.xdr': 'video/x-amt-demorun',
'.xgz': 'xgl/drawing',
'.xif': 'image/vnd.xiff',
'.xl': 'application/excel',
'.xla': 'application/excel',
'.xla': 'application/x-excel',
'.xla': 'application/x-msexcel',
'.xlb': 'application/excel',
'.xlb': 'application/vnd.ms-excel',
'.xlb': 'application/x-excel',
'.xlc': 'application/excel',
'.xlc': 'application/vnd.ms-excel',
'.xlc': 'application/x-excel',
'.xld': 'application/excel',
'.xld': 'application/x-excel',
'.xlk': 'application/excel',
'.xlk': 'application/x-excel',
'.xll': 'application/excel',
'.xll': 'application/vnd.ms-excel',
'.xll': 'application/x-excel',
'.xlm': 'application/excel',
'.xlm': 'application/vnd.ms-excel',
'.xlm': 'application/x-excel',
'.xls': 'application/excel',
'.xls': 'application/vnd.ms-excel',
'.xls': 'application/x-excel',
'.xls': 'application/x-msexcel',
'.xlt': 'application/excel',
'.xlt': 'application/x-excel',
'.xlv': 'application/excel',
'.xlv': 'application/x-excel',
'.xlw': 'application/excel',
'.xlw': 'application/vnd.ms-excel',
'.xlw': 'application/x-excel',
'.xlw': 'application/x-msexcel',
'.xm': 'audio/xm',
'.xml': 'application/xml',
'.xml': 'text/xml',
'.xmz': 'xgl/movie',
'.xpix': 'application/x-vnd.ls-xpix',
'.xpm': 'image/x-xpixmap',
'.xpm': 'image/xpm',
'.x-png': 'image/png',
'.xsr': 'video/x-amt-showrun',
'.xwd': 'image/x-xwd',
'.xwd': 'image/x-xwindowdump',
'.xyz': 'chemical/x-pdb',
'.z': 'application/x-compress',
'.z': 'application/x-compressed',
'.zip': 'application/x-compressed',
'.zip': 'application/x-zip-compressed',
'.zip': 'application/zip',
'.zip': 'multipart/x-zip',
'.zoo': 'application/octet-stream',
'.zsh': 'text/x-script.zsh',
};
const i = fileName.lastIndexOf('.');
let ext = '';
if (i > 0) { ext = fileName.substr(i); }
let mime = mimeTypes[ext];
if (mime == null) { mime = 'application/octet-stream'; }
return mime;
}
module.exports = mimeType;

20
util/randomToken.js Normal file
View File

@ -0,0 +1,20 @@
/** Used to generate file names
* @param {number} number - Number of characters the file name should be
* @returns {string} String containing file name
*/
function randomToken(number, symbols) {
// eslint-disable-next-line no-param-reassign
number = parseInt(number, 10);
let text = '';
let possible
if(symbols !== true) {
possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
} else {
possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()-_=+[]{}|;:/?><,.';
}
for (let i = 0; i < number; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
module.exports = randomToken;