summaryrefslogtreecommitdiff
path: root/server/serverstore.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/serverstore.js')
-rwxr-xr-xserver/serverstore.js161
1 files changed, 161 insertions, 0 deletions
diff --git a/server/serverstore.js b/server/serverstore.js
new file mode 100755
index 0000000..1d04530
--- /dev/null
+++ b/server/serverstore.js
@@ -0,0 +1,161 @@
+#!/usr/bin/env node
+
+var fs=require("fs"),
+ path=require("path"),
+ app=require("express")(),
+ bodyParser=require("body-parser"),
+ crypto=require("crypto"),
+ Persist=require("node-persist"),
+ glob=require("glob");
+
+var HOSTNAME="tomsmeding.com",HTTPPORT=42420;
+
+Persist.initSync({});
+
+var challenge=null;
+
+function renewChallenge(){
+ var entropy=crypto.randomBytes(512);
+ var hasher=crypto.createHash("sha256");
+ hasher.update(entropy);
+ challenge=hasher.digest("hex");
+}
+setInterval(renewChallenge,8000);
+renewChallenge();
+
+var gencode=(function(){
+ const startn=42424242;
+ const alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ var lastn=Persist.getItemSync("gencode_lastn");
+ if(lastn==null)lastn=startn;
+ return function gencode(){
+ var code="",coden=lastn;
+ while(coden){
+ code+=alphabet[coden%alphabet.length];
+ coden=~~(coden/alphabet.length);
+ }
+ if(lastn==0x7fffffff)lastn=0; //maximum value of a 32-bit int
+ else lastn++;
+ Persist.setItemSync("gencode_lastn",lastn);
+ if(lastn==startn)throw new Error("RUN OUT OF INDICES PANIC PANIC");
+ while(code.length<6)code+="a";
+ return code;
+ };
+})();
+
+
+app.use(bodyParser.raw({
+ limit:"3mb",
+ type:"image/*"
+}));
+
+app.use(bodyParser.text({
+ type:"text/plain"
+}));
+
+
+app.get("/ss/challenge",function(req,res){
+ res.end(challenge);
+});
+
+
+app.param("userid",function(req,res,next,userid){
+ var password=Persist.getItemSync("user_"+userid);
+ if(!password){
+ res.sendStatus(404);
+ res.end("Non-existent userid");
+ return;
+ }
+ req.ssuser=[userid,password];
+ next();
+});
+app.param("authhash",function(req,res,next,authhash){
+ var s=challenge+req.ssuser[1];
+ var hasher=crypto.createHash("sha256");
+ hasher.update(s);
+ var hashres=hasher.digest("hex");
+ if(hashres!=authhash){
+ res.sendStatus(403);
+ res.end("Invalid answer to challenge");
+ return;
+ }
+ next();
+});
+app.param("fname",function(req,res,next,fname){
+ req.sscode=gencode();
+ req.ssfname=req.sscode+"_"+fname.replace(/[\x00-\x1F\/]/g,"").replace(/^\.+/,"");
+ next();
+});
+app.post("/ss/image/:userid/:authhash/:fname",function(req,res){
+ try {
+ if(!fs.statSync("images").isDirectory())throw new Error;
+ } catch(e){
+ fs.mkdirSync("images");
+ if(!fs.statSync("images").isDirectory())throw new Error;
+ }
+ if(!fs.existsSync("images/"+req.ssuser[0])){
+ fs.mkdirSync("images/"+req.ssuser[0]);
+ }
+ fs.writeFileSync("images/"+req.ssuser[0]+"/"+req.ssfname,req.body);
+ res.end("https://"+HOSTNAME+"/ss/get/"+req.ssuser[0]+"/"+req.sscode);
+});
+
+
+app.param("reguserid",function(req,res,next,reguserid){
+ req.ssreguserid=reguserid;
+ next();
+});
+app.post("/ss/registerx/:reguserid",function(req,res){ //pass password in body
+ var password=req.body;
+ if(Persist.getItemSync("user_"+req.ssreguserid)){
+ res.sendStatus(409); //Conflict
+ res.end("That userid already exists");
+ return;
+ }
+ Persist.setItemSync("user_"+req.ssreguserid,password);
+ res.sendStatus(200);
+ res.end();
+});
+
+
+app.get("/ss/exists/:reguserid",function(req,res){
+ res.sendStatus(Persist.getItemSync("user_"+req.ssreguserid)?200:404);
+ res.end();
+});
+
+app.get("/ss/checklogin/:userid/:authhash",function(req,res){
+ res.sendStatus(200); //login checking is done in the authhash param
+ res.end();
+});
+
+
+app.param("ssimgcode",function(req,res,next,ssimgcode){
+ req.ssimgcode=ssimgcode.replace(/[^a-zA-Z0-9]/g,"");
+ if(req.ssimgcode.length!=6){
+ res.sendStatus(404);
+ res.end("Invalid or unknown image code");
+ return;
+ }
+ next();
+});
+app.get("/ss/get/:userid/:ssimgcode",function(req,res){
+ var files=glob.sync(__dirname+"/images/"+req.ssuser[0]+"/"+req.ssimgcode+"*");
+ if(files.length==0){
+ res.sendStatus(404);
+ res.end("Unknown image code");
+ return;
+ }
+ if(files.length>1){
+ console.log("More than one file matched; internal error");
+ console.log(files);
+ res.sendStatus(500);
+ res.end("More than one file matched; internal error");
+ return;
+ }
+ res.sendFile(files[0]);
+});
+
+
+app.listen(42420,function(){
+ console.log("Server started.");
+});