ADDED config.py Index: config.py ================================================================== --- config.py +++ config.py @@ -0,0 +1,6 @@ +# +# config.py +# +# Basic setup for notepad +# +DBNAME= "notes-4323zz.db" Index: index.html ================================================================== --- index.html +++ index.html @@ -1,29 +1,26 @@ - - Cloud Notepad - - + @@ -45,15 +42,14 @@
- + + - - Index: js/main.js ================================================================== --- js/main.js +++ js/main.js @@ -25,22 +25,22 @@ // changes to our server when our own clock is borked. let tm_off = 0.0; // Try to pull in current store on startup function startup() { - if (localStorage.getItem("tm") == null) { + if (localStorage.getItem("user") == null) { // Initial state localStorage.tm = "0.0"; server_tm = 0.0; // They need to log in login.style.display = "block"; } else { // Saved state server_tm = parseFloat(localStorage.tm); + sync(); to_menu(); } - sync(); } // Mint a new key for a new note function new_key() { while (true) { @@ -96,11 +96,11 @@ while (entries.hasChildNodes()) { entries.removeChild(entries.lastChild); } // Traverse localStorage, assemble notes - ents = []; + const ents = []; for (let idx = 0; idx < localStorage.length; ++idx) { let key = localStorage.key(idx); if (!key.startsWith("note")) { // Ignore non-note state continue; @@ -189,11 +189,11 @@ } // Create a delta of changes, so we only have to submit back things // which have changed WRT our last update from the server function save_notes() { - const upd = {} + const upd = {}; for (let idx = 0; idx < localStorage.length; ++idx) { let key = localStorage.key(idx); if (key.startsWith("note")) { let ent = JSON.parse(localStorage[key]); if (ent.tm > server_tm) { @@ -251,12 +251,13 @@ update_entries(); } // Submit our current content, including credentials const onotes = save_notes(); - onotes.user = user.value; - onotes.password = password.value; + onotes.tm = server_tm; + onotes.user = localStorage.user; + onotes.password = localStorage.password; req.send(JSON.stringify(onotes)); } // Log out (clear localStorage and PHP server side) function tool_logout() { @@ -289,11 +290,14 @@ return; } // User/pass is OK, so go to main UI login.style.display = "none"; + localStorage.user = user.value; + localStorage.password = password.value; + sync(); to_menu(); } // Submit our current content req.send(JSON.stringify(creds)); } ADDED login.py Index: login.py ================================================================== --- login.py +++ login.py @@ -0,0 +1,54 @@ +#!/usr/bin/python +# +# login.py +# Verify user/pass +# +import cgi, sys, json, time +import sqlite3 +from config import DBNAME +w = sys.stdout.write + +# Always a JSON response (even error) +w("Content-Type: application/json\n") + +# Connect to DB +# (Use a name which outsiders won't know.) +conn = sqlite3.connect("var/" + DBNAME) + +# Say we can't grok it & bail +def fail(msg): + w("Status: 400 Bad Request\n\n%s" % (json.dumps({"err": msg}),)) + sys.exit(0) + +def run(): + # Parse CGI header + cgi.maxlen = 128*1024 + fields = cgi.parse() + + # JSON body + try: + req = json.load(sys.stdin) + user = str(req["user"]) + pw = str(req["password"]) + except: + fail("Bad JSON input") + + # Logged in? + if (not user) or (not pw): + fail("Bad login credentials") + + # Verify pw + c = conn.cursor() + c.execute("select password from accounts where user=?", (user,)) + tup = c.fetchone() + c.close() + if (tup is None) or (tup[0] != pw): + fail("Bad login user '%s' pass '%s'" % (user, pw)) + + # Send back success + w("Status: 200 OK\n\n%s" % (json.dumps({"err": None}),)) + + sys.exit(0) + +if __name__ == "__main__": + run() Index: sync.py ================================================================== --- sync.py +++ sync.py @@ -3,15 +3,16 @@ # sync.py # Accept POST of new entries to our note DB # import cgi, sys, json, time import sqlite3 +from config import DBNAME w = sys.stdout.write # Connect to DB # (Use a name which outsiders won't know.) -conn = sqlite3.connect("notes-4323zz.db") +conn = sqlite3.connect("var/" + DBNAME) # This is a JSON API w("Content-Type: application/json\n") # Say we can't grok it & bail @@ -52,11 +53,11 @@ c = conn.cursor() c.execute( "select key,tm,title,content from notes where user=? and tm>?", (user, tm)) for tup in c: - onotes[tup[0]] = {"tm": tup[1], "title": tup[2], "content": tup[3]) + onotes[tup[0]] = {"tm": tup[1], "title": tup[2], "content": tup[3]} # For each note which they've changed, either accept the change, # or send back the newer content which we've already received. resp = {} changes = False @@ -104,8 +105,8 @@ conn.commit() conn.close() # Give them an update including time resp["tm"] = time.time() -w(json.dumps(resp)) +w("Status: 200 OK\n\n%s" % (json.dumps(resp),)) sys.exit(0)