#!/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 = Persist.create({ dir:__dirname+"/persist", continuous:false, interval:false }); 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(); function gencode(){ var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var code = ""; for(var i = 0; i < 6; i++) { code += alphabet[~~(Math.random() * alphabet.length)]; } 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.ssfname = 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]); } // Try until we get a unique code (enforced by "wx"), or we've failed 10 times for (var i = 0; i < 10; i++) { var code = gencode(); var path = "images/" + req.ssuser[0] + "/" + code + "_" + req.ssfname; try { fs.writeFileSync(path, req.body, {flag: "wx"}); res.end("https://" + HOSTNAME + "/ss/get/" + req.ssuser[0] + "/" + code); return; } catch(e) { if (i == 10) console.log(e); continue; } } res.sendStatus(500); res.end(); }); 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."); });