Add/Update/Remove
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
node_modules
|
node_modules
|
||||||
uploads/*
|
app/uploads/*
|
||||||
|
app/tmp
|
||||||
database.sqlite*
|
database.sqlite*
|
||||||
|
*.bak
|
||||||
|
package-lock.json
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
port = 8000;
|
port = 8000;
|
||||||
|
|
||||||
|
var log = require('loglevel');
|
||||||
|
|
||||||
|
log.setLevel(log.levels.INFO);
|
||||||
|
|
||||||
// Require the libraries:
|
// Require the libraries:
|
||||||
var SocketIOFileUpload = require('socketio-file-upload'),
|
var SocketIOFileUpload = require('socketio-file-upload'),
|
||||||
socketio = require('socket.io'),
|
socketio = require('socket.io'),
|
||||||
@@ -11,10 +15,31 @@ const app = express()
|
|||||||
const http = require('http');
|
const http = require('http');
|
||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
const { Server } = require("socket.io");
|
const { Server } = require("socket.io");
|
||||||
const { SqliteHandler, UploadObject } = require('./handlers/sqliteHandler');
|
const { SqliteHandler } = require('./handlers/sqliteHandler');
|
||||||
var fs = require('fs')
|
const { UploadObject } = require('./handlers/uploadHandler');
|
||||||
|
|
||||||
|
// Prepare directories
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
tmp = __dirname + "/tmp/";
|
||||||
|
uploadsdir = __dirname + "/uploads/";
|
||||||
|
|
||||||
|
if (!fs.existsSync(tmp)){
|
||||||
|
fs.mkdirSync(tmp);
|
||||||
|
} else {
|
||||||
|
for (const file of fs.readdirSync(tmp)) {
|
||||||
|
fs.unlinkSync(path.join(tmp, file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(uploadsdir)){
|
||||||
|
fs.mkdirSync(uploadsdir);
|
||||||
|
}
|
||||||
|
|
||||||
const io = new Server(server);
|
const io = new Server(server);
|
||||||
|
|
||||||
|
|
||||||
sqliteobj = new SqliteHandler("database.sqlite");
|
sqliteobj = new SqliteHandler("database.sqlite");
|
||||||
db = sqliteobj.getDatabaseObj();
|
db = sqliteobj.getDatabaseObj();
|
||||||
|
|
||||||
@@ -32,19 +57,38 @@ app.get('/api/download/:hash', (req, res) => {
|
|||||||
if(handler == undefined) {
|
if(handler == undefined) {
|
||||||
var handler = new UploadObject(db);
|
var handler = new UploadObject(db);
|
||||||
}
|
}
|
||||||
handler.load(req.params.hash);
|
if(handler.load(req.params.hash)){
|
||||||
if(handler.isLoaded()){
|
|
||||||
res.status(200).json({result: {
|
res.status(200).json({result: {
|
||||||
files: handler.getFiles()
|
files: handler.getFiles()
|
||||||
}, code:200})
|
}, code:200})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.get('/download/:hash/index/:index', (req, res) => {
|
||||||
|
if(handler == undefined) {
|
||||||
|
var handler = new UploadObject(db);
|
||||||
|
}
|
||||||
|
if(handler.load(req.params.hash) && typeof parseInt(req.params.index) == 'number') {
|
||||||
|
res.set("Content-Disposition", "attachment; filename=\""+handler.getFiles()[req.params.index].filename+"\"")
|
||||||
|
res.sendFile(__dirname + "/uploads/" + handler.getHash()+"/"+handler.getFiles()[req.params.index].filename);
|
||||||
|
} else {
|
||||||
|
notFound(req, res);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
app.get('/upload', (req, res) => {
|
app.get('/upload', (req, res) => {
|
||||||
res.sendFile(__dirname + "/forms/upload.html");
|
res.sendFile(__dirname + "/forms/upload.html");
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/download/(*)', (req, res) => {
|
app.get('/download', (req, res) => {
|
||||||
|
res.sendFile(__dirname + "/forms/download.html");
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/download/:hash', (req, res) => {
|
||||||
|
res.sendFile(__dirname + "/forms/download.html");
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/download/:hash/:adminhash', (req, res) => {
|
||||||
res.sendFile(__dirname + "/forms/download.html");
|
res.sendFile(__dirname + "/forms/download.html");
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -72,38 +116,58 @@ app.get('/download/(*)', (req, res) => {
|
|||||||
// var io = new socketio.Server(app.listen(port));
|
// var io = new socketio.Server(app.listen(port));
|
||||||
io.sockets.on("connection", function(socket){
|
io.sockets.on("connection", function(socket){
|
||||||
var handler = new UploadObject(db);
|
var handler = new UploadObject(db);
|
||||||
console.log(handler);
|
|
||||||
if(socket.handshake.url.startsWith("/socket.io")) {
|
if(socket.handshake.url.startsWith("/socket.io")) {
|
||||||
|
|
||||||
var uploader = new SocketIOFileUpload();
|
var uploader = new SocketIOFileUpload();
|
||||||
uploader.dir = "tmp";
|
uploader.dir = "tmp";
|
||||||
|
|
||||||
|
|
||||||
|
uploader.listen(socket);
|
||||||
|
var processed = 0;
|
||||||
|
socket.on("prepareUpload", function(num_files){
|
||||||
|
console.log("Got \"prepareUpload\" event");
|
||||||
|
console.log(num_files," Files")
|
||||||
|
if(handler.new(num_files)){
|
||||||
|
console.log("Emitting \"serverReady\" event");
|
||||||
|
socket.emit("serverReady");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
uploader.uploadValidator = function(event, callback){
|
uploader.uploadValidator = function(event, callback){
|
||||||
// asynchronous operations allowed here; when done,
|
// asynchronous operations allowed here; when done,
|
||||||
if (true) {
|
if (handler.isLoaded()) {
|
||||||
callback(true);
|
callback(true);
|
||||||
} else {
|
} else {
|
||||||
callback(false);
|
callback(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
uploader.listen(socket);
|
|
||||||
uploader.on("start", function(event){
|
uploader.on("start", function(event){
|
||||||
// console.log(handler);
|
// console.log(handler);
|
||||||
handler.new();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Do something when a file is saved:
|
// Do something when a file is saved:
|
||||||
uploader.on("saved", function(event){
|
uploader.on("saved", function(event){
|
||||||
|
if (handler.isLoaded()) {
|
||||||
|
processed++;
|
||||||
if (event.file.success) {
|
if (event.file.success) {
|
||||||
fs.renameSync(event.file.pathName, "uploads/"+handler.getDir()+"/"+event.file.name)
|
fs.renameSync(event.file.pathName, "uploads/"+handler.getDir()+"/"+event.file.name)
|
||||||
handler.registerFile(event.file.name);
|
handler.registerFile(event.file.name);
|
||||||
|
} else {
|
||||||
|
fs.unlinkSync(event.file.pathName);
|
||||||
|
}
|
||||||
|
console.log("Process Counter Updated", processed);
|
||||||
|
console.log(handler.getNumFiles());
|
||||||
|
if (handler.getNumFiles() == processed && handler.getNumFiles() > 0) {
|
||||||
|
socket.emit("linkCreated", handler.getHash(), handler.getAdminHash());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log(event.file);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
uploader.on("complete", function(event){
|
uploader.on("complete", function(event){
|
||||||
socket.emit("linkCreated", handler.getHash(), handler.getAdminHash());
|
|
||||||
});
|
});
|
||||||
// Error handler:
|
// Error handler:
|
||||||
uploader.on("error", function(event){
|
uploader.on("error", function(event){
|
||||||
@@ -147,7 +211,7 @@ app.use(function (req, res, next) {
|
|||||||
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
server.listen(port, () => {
|
||||||
console.log('listening on *:8000');
|
log.info("Server listening on *:"+port);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
<div id="select" class="container">
|
<div id="select" class="container vertical">
|
||||||
<div class="card-button-box">
|
<div class="card-button-box vertical">
|
||||||
<div class="card-button" onclick="window.location.href = document.URL+'upload'"><img src="/img/add-sharp-white.svg" alt="Upload"></div>
|
<div class="card-button" onclick="window.location.href = document.URL+'upload'"><img src="/img/add-sharp-white.svg" alt="Upload"><p id="button-selection-newupload">New Upload</div>
|
||||||
<div class="card-button" onclick="window.location.href = document.URL+'download'"><img src="/img/arrow-down-white.svg" alt="Download"></div>
|
<div class="card-button" onclick="window.location.href = document.URL+'download'"><img src="/img/arrow-down-white.svg" alt="Download"><p id="button-selection-download">Download</p></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
98
app/forms/upload.html
Normal file
98
app/forms/upload.html
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Kakubovna: Upload</title>
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Geologica:wght@800&display=swap" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="flex-container">
|
||||||
|
<div id="upload" class="container vertical">
|
||||||
|
<div class="dropZoneContainer">
|
||||||
|
<input type="file" title="" id="drop_zone" class="FileUpload" onchange="addFiles(this.files)" multiple />
|
||||||
|
<div class="dropZoneOverlay">
|
||||||
|
<p>Drag and drop your files <br />or<br />Click to add</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<table class="filelist"></table>
|
||||||
|
</div>
|
||||||
|
<button style="vertical-align:middle" class="button" onclick="startUpload()"><span>Upload </span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="js/socket.io.js"></script>
|
||||||
|
<script src="js/siofu-client.js"></script>
|
||||||
|
<script>
|
||||||
|
var selectedFiles = [];
|
||||||
|
|
||||||
|
function addFiles(files) {
|
||||||
|
Array.from(files).forEach(file => {
|
||||||
|
addFile(file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addFile(file) {
|
||||||
|
console.log(selectedFiles.find((element) => element.name == file.name))
|
||||||
|
if (selectedFiles.find((element) => element.name == file.name) == undefined) {
|
||||||
|
selectedFiles.push(file);
|
||||||
|
}
|
||||||
|
updateFileList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortString(str, maxlen = 13) {
|
||||||
|
if (str.length > maxlen) {
|
||||||
|
shortstr = str.slice(0, (maxlen - 3) / 2) + "..." + str.slice(-(maxlen - 3) / 2);
|
||||||
|
} else {
|
||||||
|
shortstr = str;
|
||||||
|
}
|
||||||
|
return shortstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFileList(maxlen = 30) {
|
||||||
|
filelist = document.getElementsByClassName("filelist")[0];
|
||||||
|
filelist.innerHTML = "";
|
||||||
|
i = 0
|
||||||
|
selectedFiles.forEach(file => {
|
||||||
|
filelist.innerHTML += "<tr title=\"" + file.name + "\"><td>" + shortString(file.name, maxlen) + "</td></tr>";
|
||||||
|
i++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var socket = io.connect(
|
||||||
|
{
|
||||||
|
forceNew: true,
|
||||||
|
extraHeaders: {
|
||||||
|
Authorization: "bsadsds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
var uploader = new SocketIOFileUpload(socket);
|
||||||
|
uploader.addEventListener("choose", function (event) {
|
||||||
|
console.log("Files Chosen: " + event.files);
|
||||||
|
});
|
||||||
|
uploader.addEventListener("progress", function (event) {
|
||||||
|
console.log("Files Chosen: " + event.bytesLoaded / event.file.size);
|
||||||
|
});
|
||||||
|
|
||||||
|
function startUpload() {
|
||||||
|
socket.once("serverReady", function (event) {
|
||||||
|
console.log("Got \"serverReady\" event");
|
||||||
|
console.log("Uploading..");
|
||||||
|
uploader.submitFiles(selectedFiles);
|
||||||
|
})
|
||||||
|
console.log("Emitting \"prepareUpload\" event");
|
||||||
|
socket.emit("prepareUpload", selectedFiles.length);
|
||||||
|
}
|
||||||
|
socket.once("linkCreated", (hash, adminhash) => {
|
||||||
|
console.log("Link Created");
|
||||||
|
window.location.href = document.location.protocol + "//" + document.location.host + "/api/download/" + hash + '/'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
44
app/handlers/sqliteHandler.js
Normal file
44
app/handlers/sqliteHandler.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
module.exports = {
|
||||||
|
|
||||||
|
SqliteHandler: class SqliteHandler {
|
||||||
|
constructor(path) {
|
||||||
|
this.loaded = false;
|
||||||
|
this.path = path;
|
||||||
|
this.db = require('better-sqlite3')(this.path);
|
||||||
|
this.db.prepare(`CREATE TABLE IF NOT EXISTS "user" (
|
||||||
|
"id" INTEGER NOT NULL UNIQUE,
|
||||||
|
"name" TEXT NOT NULL UNIQUE,
|
||||||
|
"password" TEXT NOT NULL,
|
||||||
|
"email" INTEGER,
|
||||||
|
"admin" INTEGER,
|
||||||
|
PRIMARY KEY("id" AUTOINCREMENT)
|
||||||
|
)`).run();
|
||||||
|
|
||||||
|
this.db.prepare(`CREATE TABLE IF NOT EXISTS "upload" (
|
||||||
|
"id" INTEGER NOT NULL UNIQUE,
|
||||||
|
"hashsalt" TEXT NOT NULL UNIQUE,
|
||||||
|
"adminhash" TEXT NOT NULL UNIQUE,
|
||||||
|
"desc" TEXT,
|
||||||
|
"password" TEXT,
|
||||||
|
"owner_id" INTEGER,
|
||||||
|
"upload_unix" INTEGER,
|
||||||
|
PRIMARY KEY("id" AUTOINCREMENT),
|
||||||
|
FOREIGN KEY("owner_id") REFERENCES "user"("id")
|
||||||
|
)`).run();
|
||||||
|
|
||||||
|
this.db.prepare(`CREATE TABLE IF NOT EXISTS "file" (
|
||||||
|
"id" INTEGER NOT NULL UNIQUE,
|
||||||
|
"filename" TEXT NOT NULL,
|
||||||
|
"upload_id" INTEGER NOT NULL,
|
||||||
|
"state" INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY("id" AUTOINCREMENT),
|
||||||
|
FOREIGN KEY("upload_id") REFERENCES "upload"("id")
|
||||||
|
)`).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
getDatabaseObj() {
|
||||||
|
return this.db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,25 +5,33 @@ module.exports = {
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
this.absrc = ['E', 'T', 'X', 'W', 'U', 'R', 'J', 'I', 'N', 'C'];
|
this.absrc = ['E', 'T', 'X', 'W', 'U', 'R', 'J', 'I', 'N', 'C'];
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
|
this.num_files = 0;
|
||||||
this.fileCache = {};
|
this.fileCache = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
new() {
|
new(num_files) {
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
|
if (typeof num_files == "number" && num_files > 0) {
|
||||||
|
this.num_files = num_files;
|
||||||
|
} else {
|
||||||
|
console.error("Invalid number of files");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
this.hashsalt = this.makeHash(10);
|
this.hashsalt = this.makeHash(10);
|
||||||
this.adminhash = this.makeHash(10);
|
this.adminhash = this.makeHash(10);
|
||||||
var sql = this.db.prepare(`INSERT INTO "upload" (hashsalt, adminhash, upload_unix) VALUES (?, ?, ?)`);
|
var sql = this.db.prepare(`INSERT INTO "upload" (hashsalt, adminhash, upload_unix) VALUES (?, ?, ?)`);
|
||||||
var result = sql.run(this.hashsalt, this.adminhash, Math.floor(Date.now() / 1000));
|
var result = sql.run(this.hashsalt, this.adminhash, Math.floor(Date.now() / 1000));
|
||||||
this.id = result.lastInsertRowid;
|
this.id = result.lastInsertRowid;
|
||||||
this.hashid = this.id2hashid(result.lastInsertRowid);
|
this.hashid = this.id2hashid(result.lastInsertRowid);
|
||||||
this.dir = this.hashid+this.hashsalt;
|
this.dir = this.hashid + this.hashsalt;
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
if (!fs.existsSync("uploads/"+this.dir)){
|
if (!fs.existsSync("uploads/" + this.dir)) {
|
||||||
fs.mkdirSync("uploads/"+this.dir);
|
fs.mkdirSync("uploads/" + this.dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,17 +41,37 @@ module.exports = {
|
|||||||
this.hashid = shash[0];
|
this.hashid = shash[0];
|
||||||
this.id = this.hashid2id(this.hashid)
|
this.id = this.hashid2id(this.hashid)
|
||||||
this.hashsalt = shash[1];
|
this.hashsalt = shash[1];
|
||||||
this.dir = this.hashid+this.hashsalt;
|
this.dir = this.hashid + this.hashsalt;
|
||||||
|
|
||||||
|
var sql = this.db.prepare(`SELECT count(id) AS "count" FROM "file" WHERE upload_id=?`);
|
||||||
|
var num_files = sql.get(this.id)["count"];
|
||||||
|
if (typeof num_files == "number" && num_files > 0) {
|
||||||
|
this.num_files = num_files;
|
||||||
|
} else {
|
||||||
|
console.error("Invalid number of files");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var sql = this.db.prepare(`SELECT EXISTS(SELECT 1 FROM "upload" WHERE id=? AND hashsalt=? LIMIT 1) AS "exists"`);
|
var sql = this.db.prepare(`SELECT EXISTS(SELECT 1 FROM "upload" WHERE id=? AND hashsalt=? LIMIT 1) AS "exists"`);
|
||||||
var result = sql.get(this.id, this.hashsalt);
|
var result = sql.get(this.id, this.hashsalt);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (result["exists"]) {
|
if (result["exists"]) {
|
||||||
console.log("LOADED: ", result);
|
console.log("LOADED: ", result);
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.log("Not Found");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNumFiles() {
|
||||||
|
return this.num_files;
|
||||||
|
}
|
||||||
|
|
||||||
isLoaded() {
|
isLoaded() {
|
||||||
return this.loaded;
|
return this.loaded;
|
||||||
}
|
}
|
||||||
@@ -62,6 +90,10 @@ module.exports = {
|
|||||||
return this.files;
|
return this.files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFileByIndex(index) {
|
||||||
|
return this.getFiles()[index];
|
||||||
|
}
|
||||||
|
|
||||||
registerFile(filename) {
|
registerFile(filename) {
|
||||||
var sql = this.db.prepare(`INSERT INTO "file" (filename, upload_id) VALUES (?, ?)`);
|
var sql = this.db.prepare(`INSERT INTO "file" (filename, upload_id) VALUES (?, ?)`);
|
||||||
var result = sql.run(filename, this.id);
|
var result = sql.run(filename, this.id);
|
||||||
@@ -73,7 +105,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHash() {
|
getHash() {
|
||||||
return this.hashid+this.hashsalt;
|
return this.hashid + this.hashsalt;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHashId() {
|
getHashId() {
|
||||||
@@ -122,47 +154,5 @@ module.exports = {
|
|||||||
return [hash.slice(0, hash.length - 10), hash.slice(hash.length - 10, hash.length)]
|
return [hash.slice(0, hash.length - 10), hash.slice(hash.length - 10, hash.length)]
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
SqliteHandler: class SqliteHandler {
|
|
||||||
constructor(path) {
|
|
||||||
this.loaded = false;
|
|
||||||
this.path = path;
|
|
||||||
this.db = require('better-sqlite3')(this.path);
|
|
||||||
this.db.prepare(`CREATE TABLE IF NOT EXISTS "user" (
|
|
||||||
"id" INTEGER NOT NULL UNIQUE,
|
|
||||||
"name" TEXT NOT NULL UNIQUE,
|
|
||||||
"password" TEXT NOT NULL,
|
|
||||||
"email" INTEGER,
|
|
||||||
"admin" INTEGER,
|
|
||||||
PRIMARY KEY("id" AUTOINCREMENT)
|
|
||||||
)`).run();
|
|
||||||
|
|
||||||
this.db.prepare(`CREATE TABLE IF NOT EXISTS "upload" (
|
|
||||||
"id" INTEGER NOT NULL UNIQUE,
|
|
||||||
"hashsalt" TEXT NOT NULL UNIQUE,
|
|
||||||
"adminhash" TEXT NOT NULL UNIQUE,
|
|
||||||
"desc" TEXT,
|
|
||||||
"password" TEXT,
|
|
||||||
"owner_id" INTEGER,
|
|
||||||
"upload_unix" INTEGER,
|
|
||||||
PRIMARY KEY("id" AUTOINCREMENT),
|
|
||||||
FOREIGN KEY("owner_id") REFERENCES "user"("id")
|
|
||||||
)`).run();
|
|
||||||
|
|
||||||
this.db.prepare(`CREATE TABLE IF NOT EXISTS "file" (
|
|
||||||
"id" INTEGER NOT NULL UNIQUE,
|
|
||||||
"filename" TEXT NOT NULL,
|
|
||||||
"upload_id" INTEGER NOT NULL,
|
|
||||||
"state" INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY("id" AUTOINCREMENT),
|
|
||||||
FOREIGN KEY("upload_id") REFERENCES "upload"("id")
|
|
||||||
)`).run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getDatabaseObj() {
|
|
||||||
return this.db;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^8.4.0",
|
"better-sqlite3": "^8.4.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"multer": "^1.4.5-lts.1",
|
"loglevel": "^1.8.1",
|
||||||
"socket.io": "^4.6.2",
|
"socket.io": "^4.6.2",
|
||||||
"socketio-file-upload": "^0.7.3"
|
"socketio-file-upload": "^0.7.3"
|
||||||
}
|
}
|
||||||
174
app/public/css/style.css
Normal file
174
app/public/css/style.css
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
@charset "UTF-8";
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #1b1b1b;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box__dragndrop,
|
||||||
|
.box__uploading,
|
||||||
|
.box__success,
|
||||||
|
.box__error {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
font-family: "Geologica", sans-serif;
|
||||||
|
border-radius: 15px;
|
||||||
|
border-color: black;
|
||||||
|
border-width: 2px;
|
||||||
|
border-style: solid;
|
||||||
|
background-color: #f16d01;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filelist {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filelist p {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list p {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#select {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #e42200;
|
||||||
|
border: none;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28px;
|
||||||
|
padding: 20px;
|
||||||
|
width: 200px;
|
||||||
|
transition: all 0.5s;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button span {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
transition: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button span:after {
|
||||||
|
content: "»";
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
top: 0;
|
||||||
|
right: -20px;
|
||||||
|
transition: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover span {
|
||||||
|
padding-right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover span:after {
|
||||||
|
opacity: 1;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-button-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 50px;
|
||||||
|
}
|
||||||
|
.card-button-box .card-button {
|
||||||
|
display: flex;
|
||||||
|
background-color: rgba(88, 88, 88, 0.2);
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
height: 100px;
|
||||||
|
width: 400px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
transition: 0.3s;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.card-button-box .card-button img {
|
||||||
|
height: 100%;
|
||||||
|
flex-basis: 40%;
|
||||||
|
}
|
||||||
|
.card-button-box .card-button p {
|
||||||
|
flex-basis: 60%;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-size: xx-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-button:hover {
|
||||||
|
transform: scale(1.02);
|
||||||
|
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropZoneContainer {
|
||||||
|
display: grid;
|
||||||
|
margin-left: 100px;
|
||||||
|
margin-right: 100px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropZoneOverlay, .FileUpload {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropZoneOverlay {
|
||||||
|
margin-top: -3px;
|
||||||
|
margin-left: -3px;
|
||||||
|
border: dotted 3px;
|
||||||
|
font-size: 110%;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileUpload {
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}/*# sourceMappingURL=style.css.map */
|
||||||
1
app/public/css/style.css.map
Normal file
1
app/public/css/style.css.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["style.css","style.scss"],"names":[],"mappings":"AAAA,gBAAgB;ACAhB;;EAEE,UAAA;EACA,SAAA;EACA,YAAA;ADEF;;ACEA;EACE,yBAAA;ADCF;;ACGA;EACE,cAAA;ADAF;;ACGA;;;;EAIE,aAAA;ADAF;;ACGA;EACE,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,aAAA;ADAF;;ACGA;EACE,oCAAA;EACA,mBAAA;EACA,mBAAA;EACA,iBAAA;EACA,mBAAA;EACA,yBAAA;EACA,aAAA;EACA,aAAA;EACA,kBAAA;ADAF;;ACGA;EACI,sBAAA;EACA,uBAAA;EACA,mBAAA;ADAJ;;ACGA;EACI,gBAAA;ADAJ;;ACGA;EACI,aAAA;EACA,sBAAA;EACA,UAAA;ADAJ;;ACEA;EACI,cAAA;ADCJ;;ACEA;EACI,cAAA;ADCJ;;ACEA;EACI,sBAAA;ADCJ;;ACEA;EACI,qBAAA;EACA,kBAAA;EACA,yBAAA;EACA,YAAA;EACA,cAAA;EACA,kBAAA;EACA,eAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,eAAA;EACA,WAAA;ADCJ;;ACEA;EACI,eAAA;EACA,qBAAA;EACA,kBAAA;EACA,gBAAA;ADCJ;;ACEA;EACI,YAAA;EACA,kBAAA;EACA,UAAA;EACA,MAAA;EACA,YAAA;EACA,gBAAA;ADCJ;;ACEA;EACI,mBAAA;ADCJ;;ACEA;EACI,UAAA;EACA,QAAA;ADCJ;;ACEA;EACI,aAAA;EACA,uBAAA;EACA,SAAA;ADCJ;ACAI;EACI,aAAA;EACA,uCAAA;EACA,kBAAA;EACA,aAAA;EACA,aAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;EACA,gBAAA;EACA,mBAAA;EACA,uBAAA;EACA,eAAA;ADER;ACDQ;EACI,YAAA;EACA,eAAA;ADGZ;ACAQ;EACI,eAAA;EACA,cAAA;EACA,gBAAA;EACA,mBAAA;ADEZ;;ACOA;EACI,sBAAA;EACA,2CAAA;ADJJ;;ACOA;EACI,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,WAAA;EACA,aAAA;ADJJ;;ACOA;EACI,YAAA;EACA,WAAA;EACA,cAAA;EACA,WAAA;ADJJ;;ACOA;EACI,gBAAA;EACA,iBAAA;EACA,kBAAA;EACA,eAAA;EACA,cAAA;EACA,kBAAA;EACA,sBAAA;ADJJ;;ACMA;EACI,UAAA;EACA,eAAA;ADHJ","file":"style.css"}
|
||||||
@@ -31,7 +31,7 @@ canvas {
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
font-family: 'Geologica', sans-serif;
|
font-family: 'Geologica', sans-serif;
|
||||||
border-radius: 4px;
|
border-radius: 15px;
|
||||||
border-color: black;
|
border-color: black;
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
@@ -112,29 +112,42 @@ canvas {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 50px;
|
gap: 50px;
|
||||||
}
|
.card-button {
|
||||||
|
display: flex;
|
||||||
.card-button {
|
|
||||||
background-color: rgba(88, 88, 88, 0.2);
|
background-color: rgba(88, 88, 88, 0.2);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px;
|
padding: 10px;
|
||||||
width: 200px;
|
height: 100px;
|
||||||
|
width: 400px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
height: 100%;
|
||||||
|
flex-basis: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
flex-basis: 60%;
|
||||||
|
color:#FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-size: xx-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.card-button:hover {
|
.card-button:hover {
|
||||||
transform: scale(1.02);
|
transform: scale(1.02);
|
||||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
|
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-button p {
|
|
||||||
position: absolute;
|
|
||||||
color:#FFFFFF;
|
|
||||||
font-size: x-large;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropZoneContainer {
|
.dropZoneContainer {
|
||||||
display: grid;
|
display: grid;
|
||||||
margin-left: 100px;
|
margin-left: 100px;
|
||||||
@@ -161,4 +174,5 @@ canvas {
|
|||||||
}
|
}
|
||||||
.FileUpload {
|
.FileUpload {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
|
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
@@ -1,73 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Kakubovna: Download</title>
|
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Geologica:wght@800&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="flex-container">
|
|
||||||
<div id="code-view" class="container vertical" style="display:none">
|
|
||||||
<input id="code" type="text" placeholder="Enter code">
|
|
||||||
<button onclick="loadUpload()">Submit</button>
|
|
||||||
<p id="status"></p>
|
|
||||||
</div>
|
|
||||||
<div id="file-view" class="container vertical" style="display:none">
|
|
||||||
<input id="code" type="text" placeholder="Enter code">
|
|
||||||
<button onclick="loadUpload()">Submit</button>
|
|
||||||
<p id="status"></p>
|
|
||||||
</div>
|
|
||||||
<div id="admin-file-view" class="container vertical" style="display:none">
|
|
||||||
<input id="code" type="text" placeholder="Enter code">
|
|
||||||
<button onclick="loadUpload()">Submit</button>
|
|
||||||
<p id="status"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
var hash = "";
|
|
||||||
var adminHash = "";
|
|
||||||
handleUrl();
|
|
||||||
function handleUrl() {
|
|
||||||
console.log(document.location.pathname.split("/", 4));
|
|
||||||
path = document.location.pathname.split("/", 4)
|
|
||||||
if(path[2].length > 10 && path[2] === path[2].toUpperCase()) {
|
|
||||||
hash = path[2];
|
|
||||||
if(path[3].length == 10 && path[3] === path[3].toUpperCase()) {
|
|
||||||
adminHash = path[3];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
document.getElementById("code-view").style = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
codeInput = document.getElementById("code");
|
|
||||||
statusText = document.getElementById("status");
|
|
||||||
function loadUpload() {
|
|
||||||
if (!(codeInput.value.length > 10 && codeInput.value === codeInput.value.toUpperCase())) {
|
|
||||||
statusText.innerHTML = 'Wrong Code';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch('/api/download/' + codeInput.value)
|
|
||||||
.then(
|
|
||||||
response => response.json()
|
|
||||||
).then(jsonResponse => {
|
|
||||||
console.log(jsonResponse);
|
|
||||||
|
|
||||||
if (jsonResponse.code == 404) {
|
|
||||||
statusText.innerHTML = 'Not Found';
|
|
||||||
} else if (jsonResponse.code == 200) {
|
|
||||||
statusText.innerHTML = 'Found';
|
|
||||||
} else {
|
|
||||||
statusText.innerHTML = 'Error';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><path fill="none" stroke="currentColor" stroke-linecap="square" stroke-linejoin="round" stroke-width="32" d="M256 112v288M400 256H112"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 220 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M112 268l144 144 144-144M256 392V100"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 231 B |
Reference in New Issue
Block a user