forked from cory/tildefriends
		
	Modernize. All core JS is modules. var => let.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4155 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										52
									
								
								core/auth.js
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								core/auth.js
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | |||||||
| import * as core from './core.js'; | import * as core from './core.js'; | ||||||
| import * as form from './form.js'; | import * as form from './form.js'; | ||||||
|  |  | ||||||
| var gTokens = {}; | let gTokens = {}; | ||||||
| var gDatabase = new Database("auth"); | let gDatabase = new Database("auth"); | ||||||
|  |  | ||||||
| const kRefreshInterval = 1 * 7 * 24 * 60 * 60 * 1000; | const kRefreshInterval = 1 * 7 * 24 * 60 * 60 * 1000; | ||||||
|  |  | ||||||
| @@ -75,7 +75,7 @@ function verifyPassword(password, hash) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function hashPassword(password) { | function hashPassword(password) { | ||||||
| 	var salt = bCrypt.gensalt(12); | 	let salt = bCrypt.gensalt(12); | ||||||
| 	return bCrypt.hashpw(password, salt); | 	return bCrypt.hashpw(password, salt); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -99,14 +99,14 @@ function makeAdministrator(name) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function getCookies(headers) { | function getCookies(headers) { | ||||||
| 	var cookies = {}; | 	let cookies = {}; | ||||||
|  |  | ||||||
| 	if (headers.cookie) { | 	if (headers.cookie) { | ||||||
| 		var parts = headers.cookie.split(/,|;/); | 		let parts = headers.cookie.split(/,|;/); | ||||||
| 		for (var i in parts) { | 		for (let i in parts) { | ||||||
| 			var equals = parts[i].indexOf("="); | 			let equals = parts[i].indexOf("="); | ||||||
| 			var name = parts[i].substring(0, equals).trim(); | 			let name = parts[i].substring(0, equals).trim(); | ||||||
| 			var value = parts[i].substring(equals + 1).trim(); | 			let value = parts[i].substring(equals + 1).trim(); | ||||||
| 			cookies[name] = value; | 			cookies[name] = value; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -115,18 +115,18 @@ function getCookies(headers) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function handler(request, response) { | function handler(request, response) { | ||||||
| 	var session = getCookies(request.headers).session; | 	let session = getCookies(request.headers).session; | ||||||
| 	if (request.uri == "/login") { | 	if (request.uri == "/login") { | ||||||
| 		var sessionIsNew = false; | 		let sessionIsNew = false; | ||||||
| 		var loginError; | 		let loginError; | ||||||
|  |  | ||||||
| 		var formData = form.decodeForm(request.query); | 		let formData = form.decodeForm(request.query); | ||||||
|  |  | ||||||
| 		if (request.method == "POST" || formData.submit) { | 		if (request.method == "POST" || formData.submit) { | ||||||
| 			sessionIsNew = true; | 			sessionIsNew = true; | ||||||
| 			formData = form.decodeForm(utf8Decode(request.body), formData); | 			formData = form.decodeForm(utf8Decode(request.body), formData); | ||||||
| 			if (formData.submit == "Login") { | 			if (formData.submit == "Login") { | ||||||
| 				var account = gDatabase.get("user:" + formData.name); | 				let account = gDatabase.get("user:" + formData.name); | ||||||
| 				account = account ? JSON.parse(account) : account; | 				account = account ? JSON.parse(account) : account; | ||||||
| 				if (formData.register == "1") { | 				if (formData.register == "1") { | ||||||
| 					if (!account && | 					if (!account && | ||||||
| @@ -171,15 +171,15 @@ function handler(request, response) { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		var cookie = `session=${session}; path=/; Max-Age=${kRefreshInterval}; Secure; SameSite=Strict`; | 		let cookie = `session=${session}; path=/; Max-Age=${kRefreshInterval}; Secure; SameSite=Strict`; | ||||||
| 		var entry = readSession(session); | 		let entry = readSession(session); | ||||||
| 		if (entry && formData.return) { | 		if (entry && formData.return) { | ||||||
| 			response.writeHead(303, {"Location": formData.return, "Set-Cookie": cookie}); | 			response.writeHead(303, {"Location": formData.return, "Set-Cookie": cookie}); | ||||||
| 			response.end(); | 			response.end(); | ||||||
| 		} else { | 		} else { | ||||||
| 			File.readFile("core/auth.html").then(function(data) { | 			File.readFile("core/auth.html").then(function(data) { | ||||||
| 				var html = utf8Decode(data); | 				let html = utf8Decode(data); | ||||||
| 				var contents = ""; | 				let contents = ""; | ||||||
|  |  | ||||||
| 				if (entry) { | 				if (entry) { | ||||||
| 					if (sessionIsNew) { | 					if (sessionIsNew) { | ||||||
| @@ -216,7 +216,7 @@ function handler(request, response) { | |||||||
| 					contents += '</div>\n'; | 					contents += '</div>\n'; | ||||||
| 					contents += '</form>'; | 					contents += '</form>'; | ||||||
| 				} | 				} | ||||||
| 				var text = html.replace("<!--SESSION-->", contents); | 				let text = html.replace("<!--SESSION-->", contents); | ||||||
| 				response.writeHead(200, {"Content-Type": "text/html; charset=utf-8", "Set-Cookie": cookie, "Content-Length": text.length}); | 				response.writeHead(200, {"Content-Type": "text/html; charset=utf-8", "Set-Cookie": cookie, "Content-Length": text.length}); | ||||||
| 				response.end(text); | 				response.end(text); | ||||||
| 			}).catch(function(error) { | 			}).catch(function(error) { | ||||||
| @@ -234,8 +234,8 @@ function handler(request, response) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function getPermissions(session) { | function getPermissions(session) { | ||||||
| 	var permissions; | 	let permissions; | ||||||
| 	var entry = readSession(session); | 	let entry = readSession(session); | ||||||
| 	if (entry) { | 	if (entry) { | ||||||
| 		permissions = getPermissionsForUser(entry.name); | 		permissions = getPermissionsForUser(entry.name); | ||||||
| 		permissions.authenticated = entry.name !== "guest"; | 		permissions.authenticated = entry.name !== "guest"; | ||||||
| @@ -244,9 +244,9 @@ function getPermissions(session) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function getPermissionsForUser(userName) { | function getPermissionsForUser(userName) { | ||||||
| 	var permissions = {}; | 	let permissions = {}; | ||||||
| 	if (core.globalSettings && core.globalSettings.permissions && core.globalSettings.permissions[userName]) { | 	if (core.globalSettings && core.globalSettings.permissions && core.globalSettings.permissions[userName]) { | ||||||
| 		for (var i in core.globalSettings.permissions[userName]) { | 		for (let i in core.globalSettings.permissions[userName]) { | ||||||
| 			permissions[core.globalSettings.permissions[userName][i]] = true; | 			permissions[core.globalSettings.permissions[userName][i]] = true; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -254,9 +254,9 @@ function getPermissionsForUser(userName) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function query(headers) { | function query(headers) { | ||||||
| 	var session = getCookies(headers).session; | 	let session = getCookies(headers).session; | ||||||
| 	var entry; | 	let entry; | ||||||
| 	var autologin = tildefriends.args.autologin; | 	let autologin = tildefriends.args.autologin; | ||||||
| 	if (entry = autologin ? {name: autologin} : readSession(session)) { | 	if (entry = autologin ? {name: autologin} : readSession(session)) { | ||||||
| 		return { | 		return { | ||||||
| 			session: entry, | 			session: entry, | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| "use strict"; |  | ||||||
|  |  | ||||||
| let gSocket; | let gSocket; | ||||||
| let gCredentials; | let gCredentials; | ||||||
| let gPermissions; | let gPermissions; | ||||||
| @@ -952,6 +950,27 @@ window.addEventListener("load", function() { | |||||||
| 	window.addEventListener("message", message, false); | 	window.addEventListener("message", message, false); | ||||||
| 	window.addEventListener("online", connectSocket); | 	window.addEventListener("online", connectSocket); | ||||||
| 	document.getElementById("name").value = window.location.pathname; | 	document.getElementById("name").value = window.location.pathname; | ||||||
|  | 	document.getElementById('edit_link').addEventListener('click', function(event) { | ||||||
|  |  		event.preventDefault(); | ||||||
|  | 		toggleEdit(); | ||||||
|  | 	}); | ||||||
|  | 	document.getElementById('show_permissions_link').addEventListener('click', () => showPermissions()); | ||||||
|  | 	document.getElementById('files_hide').addEventListener('click', () => hideFiles()); | ||||||
|  | 	document.getElementById('files_show').addEventListener('click', () => showFiles()); | ||||||
|  | 	document.getElementById('closeStats').addEventListener('click', () => closeStats()); | ||||||
|  | 	document.getElementById('closeEditor').addEventListener('click', () => closeEditor()); | ||||||
|  | 	document.getElementById('save').addEventListener('click', () => save()); | ||||||
|  | 	document.getElementById('delete').addEventListener('click', () => deleteApp()); | ||||||
|  | 	document.getElementById('trace_button').addEventListener('click', function(event) { | ||||||
|  |  		event.preventDefault(); | ||||||
|  | 		trace(); | ||||||
|  | 	}); | ||||||
|  | 	document.getElementById('stats_button').addEventListener('click', function(event) { | ||||||
|  |  		event.preventDefault(); | ||||||
|  | 		toggleStats(); | ||||||
|  | 	}); | ||||||
|  | 	document.getElementById('new_file_button').addEventListener('click', () => newFile()); | ||||||
|  | 	document.getElementById('remove_file_button').addEventListener('click', () => removeFile()); | ||||||
| 	for (let tag of document.getElementsByTagName('a')) { | 	for (let tag of document.getElementsByTagName('a')) { | ||||||
| 		if (tag.accessKey) { | 		if (tag.accessKey) { | ||||||
| 			tag.classList.add('tooltip_parent'); | 			tag.classList.add('tooltip_parent'); | ||||||
|   | |||||||
							
								
								
									
										152
									
								
								core/core.js
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								core/core.js
									
									
									
									
									
								
							| @@ -2,9 +2,9 @@ import * as auth from './auth.js'; | |||||||
| import * as app from './app.js'; | import * as app from './app.js'; | ||||||
| import * as httpd from './httpd.js'; | import * as httpd from './httpd.js'; | ||||||
|  |  | ||||||
| var gProcessIndex = 0; | let gProcessIndex = 0; | ||||||
| var gProcesses = {}; | let gProcesses = {}; | ||||||
| var gStatsTimer = false; | let gStatsTimer = false; | ||||||
|  |  | ||||||
| const k_global_settings = { | const k_global_settings = { | ||||||
| 	index: { | 	index: { | ||||||
| @@ -34,20 +34,20 @@ const k_global_settings = { | |||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| var gGlobalSettings = { | let gGlobalSettings = { | ||||||
| 	index: "/~core/apps/", | 	index: "/~core/apps/", | ||||||
| }; | }; | ||||||
|  |  | ||||||
| var kGlobalSettingsFile = "data/global/settings.json"; | let kGlobalSettingsFile = "data/global/settings.json"; | ||||||
|  |  | ||||||
| var kPingInterval = 60 * 1000; | let kPingInterval = 60 * 1000; | ||||||
|  |  | ||||||
| function printError(out, error) { | function printError(out, error) { | ||||||
| 	if (error.stackTrace) { | 	if (error.stackTrace) { | ||||||
| 		out.print(error.fileName + ":" + error.lineNumber + ": " + error.message); | 		out.print(error.fileName + ":" + error.lineNumber + ": " + error.message); | ||||||
| 		out.print(error.stackTrace); | 		out.print(error.stackTrace); | ||||||
| 	} else { | 	} else { | ||||||
| 		for (var i in error) { | 		for (let i in error) { | ||||||
| 			out.print(i); | 			out.print(i); | ||||||
| 		} | 		} | ||||||
| 		out.print(error.toString()); | 		out.print(error.toString()); | ||||||
| @@ -55,9 +55,9 @@ function printError(out, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function invoke(handlers, argv) { | function invoke(handlers, argv) { | ||||||
| 	var promises = []; | 	let promises = []; | ||||||
| 	if (handlers) { | 	if (handlers) { | ||||||
| 		for (var i = 0; i < handlers.length; ++i) { | 		for (let i = 0; i < handlers.length; ++i) { | ||||||
| 			try { | 			try { | ||||||
| 				promises.push(handlers[i](...argv)); | 				promises.push(handlers[i](...argv)); | ||||||
| 			} catch (error) { | 			} catch (error) { | ||||||
| @@ -71,9 +71,9 @@ function invoke(handlers, argv) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function broadcastEvent(eventName, argv) { | function broadcastEvent(eventName, argv) { | ||||||
| 	var promises = []; | 	let promises = []; | ||||||
| 	for (var i in gProcesses) { | 	for (let i in gProcesses) { | ||||||
| 		var process = gProcesses[i]; | 		let process = gProcesses[i]; | ||||||
| 		if (process.eventHandlers[eventName]) { | 		if (process.eventHandlers[eventName]) { | ||||||
| 			promises.push(invoke(process.eventHandlers[eventName], argv)); | 			promises.push(invoke(process.eventHandlers[eventName], argv)); | ||||||
| 		} | 		} | ||||||
| @@ -82,14 +82,14 @@ function broadcastEvent(eventName, argv) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function broadcast(message) { | function broadcast(message) { | ||||||
| 	var sender = this; | 	let sender = this; | ||||||
| 	var promises = []; | 	let promises = []; | ||||||
| 	for (var i in gProcesses) { | 	for (let i in gProcesses) { | ||||||
| 		var process = gProcesses[i]; | 		let process = gProcesses[i]; | ||||||
| 		if (process != sender | 		if (process != sender | ||||||
| 			&& process.packageOwner == sender.packageOwner | 			&& process.packageOwner == sender.packageOwner | ||||||
| 			&& process.packageName == sender.packageName) { | 			&& process.packageName == sender.packageName) { | ||||||
| 			var from = getUser(process, sender); | 			let from = getUser(process, sender); | ||||||
| 			promises.push(postMessageInternal(from, process, message)); | 			promises.push(postMessageInternal(from, process, message)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -119,9 +119,9 @@ function getApps(user, process) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (user) { | 	if (user) { | ||||||
| 		var db = new Database(user); | 		let db = new Database(user); | ||||||
| 		try { | 		try { | ||||||
| 			var names = JSON.parse(db.get('apps')); | 			let names = JSON.parse(db.get('apps')); | ||||||
| 			return Object.fromEntries(names.map(name => [name, db.get('path:' + name)])); | 			return Object.fromEntries(names.map(name => [name, db.get('path:' + name)])); | ||||||
| 		} catch { | 		} catch { | ||||||
| 		} | 		} | ||||||
| @@ -136,9 +136,9 @@ function postMessageInternal(from, to, message) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function getSessionProcessBlob(blobId, session, options) { | async function getSessionProcessBlob(blobId, session, options) { | ||||||
| 	var actualOptions = {timeout: kPingInterval}; | 	let actualOptions = {timeout: kPingInterval}; | ||||||
| 	if (options) { | 	if (options) { | ||||||
| 		for (var i in options) { | 		for (let i in options) { | ||||||
| 			actualOptions[i] = options[i]; | 			actualOptions[i] = options[i]; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -148,7 +148,7 @@ async function getSessionProcessBlob(blobId, session, options) { | |||||||
| let gManifestCache = {}; | let gManifestCache = {}; | ||||||
|  |  | ||||||
| async function getProcessBlob(blobId, key, options) { | async function getProcessBlob(blobId, key, options) { | ||||||
| 	var process = gProcesses[key]; | 	let process = gProcesses[key]; | ||||||
| 	if (!process | 	if (!process | ||||||
| 		&& !(options && "create" in options && !options.create)) { | 		&& !(options && "create" in options && !options.create)) { | ||||||
| 		try { | 		try { | ||||||
| @@ -165,8 +165,8 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 			process.lastPing = null; | 			process.lastPing = null; | ||||||
| 			process.timeout = options.timeout; | 			process.timeout = options.timeout; | ||||||
| 			process.stats = false; | 			process.stats = false; | ||||||
| 			var resolveReady; | 			let resolveReady; | ||||||
| 			var rejectReady; | 			let rejectReady; | ||||||
| 			process.ready = new Promise(function(resolve, reject) { | 			process.ready = new Promise(function(resolve, reject) { | ||||||
| 				resolveReady = resolve; | 				resolveReady = resolve; | ||||||
| 				rejectReady = reject; | 				rejectReady = reject; | ||||||
| @@ -177,7 +177,7 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 				process.task = null; | 				process.task = null; | ||||||
| 				delete gProcesses[key]; | 				delete gProcesses[key]; | ||||||
| 			}; | 			}; | ||||||
| 			var imports = { | 			let imports = { | ||||||
| 				'core': { | 				'core': { | ||||||
| 					'broadcast': broadcast.bind(process), | 					'broadcast': broadcast.bind(process), | ||||||
| 					'register': function(eventName, handler) { | 					'register': function(eventName, handler) { | ||||||
| @@ -352,11 +352,11 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 				process.credentials.session && | 				process.credentials.session && | ||||||
| 				process.credentials.session.name) { | 				process.credentials.session.name) { | ||||||
| 				imports.database = function(key) { | 				imports.database = function(key) { | ||||||
| 					var db = new Database(process.credentials.session.name + ':' + key); | 					let db = new Database(process.credentials.session.name + ':' + key); | ||||||
| 					return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); | 					return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); | ||||||
| 				}; | 				}; | ||||||
| 				imports.my_shared_database = function(packageName, key) { | 				imports.my_shared_database = function(packageName, key) { | ||||||
| 					var db = new Database(':shared:' + process.credentials.session.name + ':' + packageName + ':' + key); | 					let db = new Database(':shared:' + process.credentials.session.name + ':' + packageName + ':' + key); | ||||||
| 					return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); | 					return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); | ||||||
| 				}; | 				}; | ||||||
| 				imports.databases = function() { | 				imports.databases = function() { | ||||||
| @@ -365,7 +365,7 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 			} | 			} | ||||||
| 			if (options.packageOwner && options.packageName) { | 			if (options.packageOwner && options.packageName) { | ||||||
| 				imports.shared_database = function(key) { | 				imports.shared_database = function(key) { | ||||||
| 					var db = new Database(':shared:' + options.packageOwner + ':' + options.packageName + ':' + key); | 					let db = new Database(':shared:' + options.packageOwner + ':' + options.packageName + ':' + key); | ||||||
| 					return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); | 					return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @@ -380,14 +380,14 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 			process.task.setImports(imports); | 			process.task.setImports(imports); | ||||||
| 			process.task.activate(); | 			process.task.activate(); | ||||||
| 			let source = await getBlobOrContent(blobId); | 			let source = await getBlobOrContent(blobId); | ||||||
| 			var appSourceName = blobId; | 			let appSourceName = blobId; | ||||||
| 			var appSource = utf8Decode(source); | 			let appSource = utf8Decode(source); | ||||||
| 			try { | 			try { | ||||||
| 				var appObject = JSON.parse(appSource); | 				let appObject = JSON.parse(appSource); | ||||||
| 				if (appObject.type == "tildefriends-app") { | 				if (appObject.type == "tildefriends-app") { | ||||||
| 					appSourceName = 'app.js'; | 					appSourceName = 'app.js'; | ||||||
| 					var id = appObject.files[appSourceName]; | 					let id = appObject.files[appSourceName]; | ||||||
| 					var blob = await getBlobOrContent(id); | 					let blob = await getBlobOrContent(id); | ||||||
| 					appSource = utf8Decode(blob); | 					appSource = utf8Decode(blob); | ||||||
| 					await process.task.loadFile(['/tfrpc.js', await File.readFile('core/tfrpc.js')]); | 					await process.task.loadFile(['/tfrpc.js', await File.readFile('core/tfrpc.js')]); | ||||||
| 					await Promise.all(Object.keys(appObject.files).map(async function(f) { | 					await Promise.all(Object.keys(appObject.files).map(async function(f) { | ||||||
| @@ -425,7 +425,7 @@ function setGlobalSettings(settings) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| var kStaticFiles = [ | let kStaticFiles = [ | ||||||
| 	{uri: '/', path: 'index.html', type: 'text/html; charset=UTF-8'}, | 	{uri: '/', path: 'index.html', type: 'text/html; charset=UTF-8'}, | ||||||
| 	{uri: '/style.css', type: 'text/css; charset=UTF-8'}, | 	{uri: '/style.css', type: 'text/css; charset=UTF-8'}, | ||||||
| 	{uri: '/favicon.png', type: 'image/png'}, | 	{uri: '/favicon.png', type: 'image/png'}, | ||||||
| @@ -436,8 +436,8 @@ var kStaticFiles = [ | |||||||
|  |  | ||||||
| function startsWithBytes(data, bytes) { | function startsWithBytes(data, bytes) { | ||||||
| 	if (data.byteLength >= bytes.length) { | 	if (data.byteLength >= bytes.length) { | ||||||
| 		var dataBytes = new Uint8Array(data.slice(0, bytes.length)); | 		let dataBytes = new Uint8Array(data.slice(0, bytes.length)); | ||||||
| 		for (var i = 0; i < bytes.length; i++) { | 		for (let i = 0; i < bytes.length; i++) { | ||||||
| 			if (dataBytes[i] != bytes[i] && bytes[i] !== null) { | 			if (dataBytes[i] != bytes[i] && bytes[i] !== null) { | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| @@ -447,10 +447,10 @@ function startsWithBytes(data, bytes) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function staticFileHandler(request, response, blobId, uri) { | async function staticFileHandler(request, response, blobId, uri) { | ||||||
| 	for (var i in kStaticFiles) { | 	for (let i in kStaticFiles) { | ||||||
| 		if (uri === kStaticFiles[i].uri) { | 		if (uri === kStaticFiles[i].uri) { | ||||||
| 			var path = kStaticFiles[i].path || uri.substring(1); | 			let path = kStaticFiles[i].path || uri.substring(1); | ||||||
| 			var type = kStaticFiles[i].type || guessType(path); | 			let type = kStaticFiles[i].type || guessType(path); | ||||||
|  |  | ||||||
| 			let stat = await File.stat('core/' + path); | 			let stat = await File.stat('core/' + path); | ||||||
| 			let id = `${stat.mtime}_${stat.size}`; | 			let id = `${stat.mtime}_${stat.size}`; | ||||||
| @@ -459,7 +459,7 @@ async function staticFileHandler(request, response, blobId, uri) { | |||||||
| 				response.writeHead(304, {}); | 				response.writeHead(304, {}); | ||||||
| 				response.end(); | 				response.end(); | ||||||
| 			} else { | 			} else { | ||||||
| 				var data = await File.readFile('core/' + path); | 				let data = await File.readFile('core/' + path); | ||||||
| 				response.writeHead(200, Object.assign( | 				response.writeHead(200, Object.assign( | ||||||
| 					{ | 					{ | ||||||
| 						'Content-Type': type, | 						'Content-Type': type, | ||||||
| @@ -486,7 +486,7 @@ const k_mime_types = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| async function staticDirectoryHandler(request, response, directory, uri) { | async function staticDirectoryHandler(request, response, directory, uri) { | ||||||
| 	var filename = uri || 'index.html'; | 	let filename = uri || 'index.html'; | ||||||
| 	if (filename.indexOf('..') != -1) { | 	if (filename.indexOf('..') != -1) { | ||||||
| 		response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length}); | 		response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length}); | ||||||
| 		response.end("File not found"); | 		response.end("File not found"); | ||||||
| @@ -501,7 +501,7 @@ async function staticDirectoryHandler(request, response, directory, uri) { | |||||||
| 			response.writeHead(304, {}); | 			response.writeHead(304, {}); | ||||||
| 			response.end(); | 			response.end(); | ||||||
| 		} else { | 		} else { | ||||||
| 			var data = await File.readFile(directory + filename); | 			let data = await File.readFile(directory + filename); | ||||||
| 			response.writeHead(200, { | 			response.writeHead(200, { | ||||||
| 				'Content-Type': k_mime_types[filename.split('.').pop()] || 'text/plain', | 				'Content-Type': k_mime_types[filename.split('.').pop()] || 'text/plain', | ||||||
| 				'Content-Length': data.byteLength, | 				'Content-Length': data.byteLength, | ||||||
| @@ -516,7 +516,7 @@ async function staticDirectoryHandler(request, response, directory, uri) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function wellKnownHandler(request, response, path) { | async function wellKnownHandler(request, response, path) { | ||||||
| 	var data = await File.readFile("data/global/.well-known/" + path); | 	let data = await File.readFile("data/global/.well-known/" + path); | ||||||
| 	if (data) { | 	if (data) { | ||||||
| 		response.writeHead(200, {"Content-Type": "text/plain", "Content-Length": data.length}); | 		response.writeHead(200, {"Content-Type": "text/plain", "Content-Length": data.length}); | ||||||
| 		response.end(data); | 		response.end(data); | ||||||
| @@ -578,12 +578,12 @@ function guessType(path) { | |||||||
| 		'js': 'text/javascript', | 		'js': 'text/javascript', | ||||||
| 		'svg': 'image/svg+xml', | 		'svg': 'image/svg+xml', | ||||||
| 	}; | 	}; | ||||||
| 	var extension = path.split('.').pop(); | 	let extension = path.split('.').pop(); | ||||||
| 	return k_extension_to_type[extension]; | 	return k_extension_to_type[extension]; | ||||||
| } | } | ||||||
|  |  | ||||||
| async function blobHandler(request, response, blobId, uri) { | async function blobHandler(request, response, blobId, uri) { | ||||||
| 	for (var i in kStaticFiles) { | 	for (let i in kStaticFiles) { | ||||||
| 		if (uri === kStaticFiles[i].uri && kStaticFiles[i].path) { | 		if (uri === kStaticFiles[i].uri && kStaticFiles[i].path) { | ||||||
| 			let stat = await File.stat('core/' + kStaticFiles[i].path); | 			let stat = await File.stat('core/' + kStaticFiles[i].path); | ||||||
| 			let id = `${stat.mtime}_${stat.size}`; | 			let id = `${stat.mtime}_${stat.size}`; | ||||||
| @@ -592,7 +592,7 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 				response.writeHead(304, {}); | 				response.writeHead(304, {}); | ||||||
| 				response.end(); | 				response.end(); | ||||||
| 			} else { | 			} else { | ||||||
| 				var data = await File.readFile('core/' + kStaticFiles[i].path); | 				let data = await File.readFile('core/' + kStaticFiles[i].path); | ||||||
| 				response.writeHead(200, Object.assign( | 				response.writeHead(200, Object.assign( | ||||||
| 					{ | 					{ | ||||||
| 						'Content-Type': kStaticFiles[i].type, | 						'Content-Type': kStaticFiles[i].type, | ||||||
| @@ -612,11 +612,12 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var process; | 	let process; | ||||||
| 	if (uri == "/view") { | 	if (uri == "/view") { | ||||||
| 		var data; | 		let data; | ||||||
|  | 		let match; | ||||||
| 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | ||||||
| 			var id = await new Database(match[1]).get('path:' + match[2]); | 			let id = await new Database(match[1]).get('path:' + match[2]); | ||||||
| 			if (id) { | 			if (id) { | ||||||
| 				if (request.headers['if-none-match'] === '"' + id + '"') { | 				if (request.headers['if-none-match'] === '"' + id + '"') { | ||||||
| 					response.writeHead(304, {}); | 					response.writeHead(304, {}); | ||||||
| @@ -624,7 +625,7 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 				} else { | 				} else { | ||||||
| 					data = await getBlobOrContent(id); | 					data = await getBlobOrContent(id); | ||||||
| 					if (match[3]) { | 					if (match[3]) { | ||||||
| 						var appObject = JSON.parse(data); | 						let appObject = JSON.parse(data); | ||||||
| 						data = appObject.files[match[3]]; | 						data = appObject.files[match[3]]; | ||||||
| 					} | 					} | ||||||
| 					sendData(response, data, undefined, {etag: '"' + id + '"'}); | 					sendData(response, data, undefined, {etag: '"' + id + '"'}); | ||||||
| @@ -647,17 +648,17 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} else if (uri == "/save") { | 	} else if (uri == "/save") { | ||||||
| 		var match; | 		let match; | ||||||
| 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | ||||||
| 			let newBlobId = await ssb.blobStore(request.body); | 			let newBlobId = await ssb.blobStore(request.body); | ||||||
| 			var user = match[1]; | 			let user = match[1]; | ||||||
| 			var appName = match[2]; | 			let appName = match[2]; | ||||||
| 			var credentials = auth.query(request.headers); | 			let credentials = auth.query(request.headers); | ||||||
| 			if (credentials && credentials.session && | 			if (credentials && credentials.session && | ||||||
| 				(credentials.session.name == user || | 				(credentials.session.name == user || | ||||||
| 				(credentials.permissions.administration && user == 'core'))) { | 				(credentials.permissions.administration && user == 'core'))) { | ||||||
| 				var database = new Database(user); | 				let database = new Database(user); | ||||||
| 				var apps = new Set(); | 				let apps = new Set(); | ||||||
| 				let apps_original = database.get('apps'); | 				let apps_original = database.get('apps'); | ||||||
| 				try { | 				try { | ||||||
| 					apps = new Set(JSON.parse(apps_original)); | 					apps = new Set(JSON.parse(apps_original)); | ||||||
| @@ -691,14 +692,14 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 	} else if (uri == "/delete") { | 	} else if (uri == "/delete") { | ||||||
| 		let match; | 		let match; | ||||||
| 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | ||||||
| 			var user = match[1]; | 			let user = match[1]; | ||||||
| 			var appName = match[2]; | 			let appName = match[2]; | ||||||
| 			var credentials = auth.query(request.headers); | 			let credentials = auth.query(request.headers); | ||||||
| 			if (credentials && credentials.session && | 			if (credentials && credentials.session && | ||||||
| 				(credentials.session.name == user || | 				(credentials.session.name == user || | ||||||
| 				(credentials.permissions.administration && user == 'core'))) { | 				(credentials.permissions.administration && user == 'core'))) { | ||||||
| 				var database = new Database(user); | 				let database = new Database(user); | ||||||
| 				var apps = new Set(); | 				let apps = new Set(); | ||||||
| 				try { | 				try { | ||||||
| 					apps = new Set(JSON.parse(database.get('apps'))); | 					apps = new Set(JSON.parse(database.get('apps'))); | ||||||
| 				} catch { | 				} catch { | ||||||
| @@ -717,12 +718,13 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 		response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"}); | 		response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"}); | ||||||
| 		response.end('OK'); | 		response.end('OK'); | ||||||
| 	} else { | 	} else { | ||||||
| 		var data; | 		let data; | ||||||
| 		var type; | 		let type; | ||||||
| 		var headers; | 		let headers; | ||||||
|  | 		let match; | ||||||
| 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | 		if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) { | ||||||
| 			var db = new Database(match[1]); | 			let db = new Database(match[1]); | ||||||
| 			var id = await db.get('path:' + match[2]); | 			let id = await db.get('path:' + match[2]); | ||||||
| 			if (id) { | 			if (id) { | ||||||
| 				if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') { | 				if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') { | ||||||
| 					headers = { | 					headers = { | ||||||
| @@ -732,7 +734,7 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 					response.end(); | 					response.end(); | ||||||
| 				} else { | 				} else { | ||||||
| 					data = utf8Decode(await getBlobOrContent(id)); | 					data = utf8Decode(await getBlobOrContent(id)); | ||||||
| 					var appObject = JSON.parse(data); | 					let appObject = JSON.parse(data); | ||||||
| 					data = appObject.files[uri.substring(1)]; | 					data = appObject.files[uri.substring(1)]; | ||||||
| 					data = await getBlobOrContent(data); | 					data = await getBlobOrContent(data); | ||||||
| 					type = guessType(uri); | 					type = guessType(uri); | ||||||
| @@ -747,7 +749,7 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			data = utf8Decode(await getBlobOrContent(blobId)); | 			data = utf8Decode(await getBlobOrContent(blobId)); | ||||||
| 			var appObject = JSON.parse(data); | 			let appObject = JSON.parse(data); | ||||||
| 			data = appObject.files[uri.substring(1)]; | 			data = appObject.files[uri.substring(1)]; | ||||||
| 			data = await getBlobOrContent(data); | 			data = await getBlobOrContent(data); | ||||||
| 			headers = { | 			headers = { | ||||||
| @@ -767,10 +769,10 @@ ssb.addEventListener('connections', function() { | |||||||
| }); | }); | ||||||
|  |  | ||||||
| async function loadSettings() { | async function loadSettings() { | ||||||
| 	var data; | 	let data; | ||||||
|  |  | ||||||
| 	try { | 	try { | ||||||
| 		var settings = new Database('core').get('settings'); | 		let settings = new Database('core').get('settings'); | ||||||
| 		if (settings) { | 		if (settings) { | ||||||
| 			data = JSON.parse(settings); | 			data = JSON.parse(settings); | ||||||
| 		} | 		} | ||||||
| @@ -816,7 +818,7 @@ function enableStats(process, enabled) { | |||||||
| loadSettings().then(function() { | loadSettings().then(function() { | ||||||
| 	httpd.all("/login", auth.handler); | 	httpd.all("/login", auth.handler); | ||||||
| 	httpd.all("", function(request, response) { | 	httpd.all("", function(request, response) { | ||||||
| 		var match; | 		let match; | ||||||
| 		if (request.uri === "/" || request.uri === "") { | 		if (request.uri === "/" || request.uri === "") { | ||||||
| 			response.writeHead(303, {"Location": (request.client.tls ? 'https://' : 'http://') + request.headers.host + gGlobalSettings.index, "Content-Length": "0"}); | 			response.writeHead(303, {"Location": (request.client.tls ? 'https://' : 'http://') + request.headers.host + gGlobalSettings.index, "Content-Length": "0"}); | ||||||
| 			return response.end(); | 			return response.end(); | ||||||
| @@ -837,15 +839,15 @@ loadSettings().then(function() { | |||||||
| 		} else if (match = /^(.*)(\/(?:save|delete)?)$/.exec(request.uri)) { | 		} else if (match = /^(.*)(\/(?:save|delete)?)$/.exec(request.uri)) { | ||||||
| 			return blobHandler(request, response, match[1], match[2]); | 			return blobHandler(request, response, match[1], match[2]); | ||||||
| 		} else if (match = /^\/trace$/.exec(request.uri)) { | 		} else if (match = /^\/trace$/.exec(request.uri)) { | ||||||
| 			var data = trace(); | 			let data = trace(); | ||||||
| 			response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()}); | 			response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()}); | ||||||
| 			return response.end(data); | 			return response.end(data); | ||||||
| 		} else if (match = /^\/disconnections$/.exec(request.uri)) { | 		} else if (match = /^\/disconnections$/.exec(request.uri)) { | ||||||
| 			var data = utf8Encode(JSON.stringify(disconnectionsDebug(), null, 2)); | 			let data = utf8Encode(JSON.stringify(disconnectionsDebug(), null, 2)); | ||||||
| 			response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.byteLength.toString()}); | 			response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.byteLength.toString()}); | ||||||
| 			return response.end(data); | 			return response.end(data); | ||||||
| 		} else if (match = /^\/debug$/.exec(request.uri)) { | 		} else if (match = /^\/debug$/.exec(request.uri)) { | ||||||
| 			var data = JSON.stringify(getDebug(), null, 2); | 			let data = JSON.stringify(getDebug(), null, 2); | ||||||
| 			response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()}); | 			response.writeHead(200, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()}); | ||||||
| 			return response.end(data); | 			return response.end(data); | ||||||
| 		} else if (request.uri == "/robots.txt") { | 		} else if (request.uri == "/robots.txt") { | ||||||
| @@ -853,7 +855,7 @@ loadSettings().then(function() { | |||||||
| 		} else if ((match = /^\/.well-known\/(.*)/.exec(request.uri)) && request.uri.indexOf("..") == -1) { | 		} else if ((match = /^\/.well-known\/(.*)/.exec(request.uri)) && request.uri.indexOf("..") == -1) { | ||||||
| 			return wellKnownHandler(request, response, match[1]); | 			return wellKnownHandler(request, response, match[1]); | ||||||
| 		} else { | 		} else { | ||||||
| 			var data = "File not found."; | 			let data = "File not found."; | ||||||
| 			response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": data.length.toString()}); | 			response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": data.length.toString()}); | ||||||
| 			return response.end(data); | 			return response.end(data); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| import * as core from './core.js'; | import * as core from './core.js'; | ||||||
|  |  | ||||||
| "use strict"; |  | ||||||
|  |  | ||||||
| let gHandlers = []; | let gHandlers = []; | ||||||
| let gSocketHandlers = []; | let gSocketHandlers = []; | ||||||
| let gBadRequests = {}; | let gBadRequests = {}; | ||||||
|   | |||||||
| @@ -11,8 +11,8 @@ | |||||||
| 			<span>😎</span> | 			<span>😎</span> | ||||||
| 			<a accesskey="h" data-tip="Open home app." href="/" style="color: #fff">Tilde Friends</a> | 			<a accesskey="h" data-tip="Open home app." href="/" style="color: #fff">Tilde Friends</a> | ||||||
| 			<a accesskey="a" data-tip="Open apps list." href="/~core/apps/">apps</a> | 			<a accesskey="a" data-tip="Open apps list." href="/~core/apps/">apps</a> | ||||||
| 			<a accesskey="e" data-tip="Toggle the app editor." href="#" onclick="event.preventDefault(); toggleEdit()">edit</a> | 			<a accesskey="e" data-tip="Toggle the app editor." href="#" id="edit_link">edit</a> | ||||||
| 			<a accesskey="p" data-tip="View and change permissions." href="#" onclick="showPermissions()">🎛️</a> | 			<a accesskey="p" data-tip="View and change permissions." href="#" id="show_permissions_link">🎛️</a> | ||||||
| 			<span id="status"></span> | 			<span id="status"></span> | ||||||
| 			<span id="requests"></span> | 			<span id="requests"></span> | ||||||
| 			<span id="permissions_settings"></span> | 			<span id="permissions_settings"></span> | ||||||
| @@ -22,31 +22,31 @@ | |||||||
| 		<div id="content" class="hbox" style="flex: 1 1; width: 100%"> | 		<div id="content" class="hbox" style="flex: 1 1; width: 100%"> | ||||||
| 			<div id="statsPane" class="vbox" style="display: none; flex 1 1"> | 			<div id="statsPane" class="vbox" style="display: none; flex 1 1"> | ||||||
| 				<div class="hbox"> | 				<div class="hbox"> | ||||||
| 					<input type="button" id="closeStats" name="closeStats" value="Close" onclick="closeStats()"> | 					<input type="button" id="closeStats" name="closeStats" value="Close"> | ||||||
| 				</div> | 				</div> | ||||||
| 				<div id="graphs" class="vbox" style="height: 100%"></div> | 				<div id="graphs" class="vbox" style="height: 100%"></div> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div id="editPane" class="vbox" style="display: none"> | 			<div id="editPane" class="vbox" style="display: none"> | ||||||
| 				<div class="navigation hbox"> | 				<div class="navigation hbox"> | ||||||
| 					<input type="button" id="closeEditor" name="closeEditor" value="Close" onclick="closeEditor()"> | 					<input type="button" id="closeEditor" name="closeEditor" value="Close"> | ||||||
| 					<input type="button" id="save" name="save" value="Save" onclick="save()"> | 					<input type="button" id="save" name="save" value="Save"> | ||||||
| 					<input type="text" id="name" name="name" style="flex: 1 1; min-width: 1em"></input> | 					<input type="text" id="name" name="name" style="flex: 1 1; min-width: 1em"></input> | ||||||
| 					<input type="button" id="delete" name="delete" value="Delete" onclick="deleteApp()"> | 					<input type="button" id="delete" name="delete" value="Delete"> | ||||||
| 					<input type="button" onclick="event.preventDefault(); trace()" value="Trace"> | 					<input type="button" id="trace_button" value="Trace"> | ||||||
| 					<input type="button" onclick="event.preventDefault(); toggleStats()" value="Stats"> | 					<input type="button" id="stats_button" value="Stats"> | ||||||
| 				</div> | 				</div> | ||||||
| 				<div class="hbox" style="height: 100%"> | 				<div class="hbox" style="height: 100%"> | ||||||
| 					<div id="filesPane"> | 					<div id="filesPane"> | ||||||
| 						<div class="hbox"> | 						<div class="hbox"> | ||||||
| 							<span id="files_header">Files</span> | 							<span id="files_header">Files</span> | ||||||
| 							<span id="files_hide" onclick="hideFiles()">«</span> | 							<span id="files_hide">«</span> | ||||||
| 							<span id="files_show" onclick="showFiles()">»</span> | 							<span id="files_show">»</span> | ||||||
| 						</div> | 						</div> | ||||||
| 						<div id="files_content"> | 						<div id="files_content"> | ||||||
| 							<ul id="files"></ul> | 							<ul id="files"></ul> | ||||||
| 							<br> | 							<br> | ||||||
| 							<div><button onclick="newFile()">New File</button></div> | 							<div><button id="new_file_button">New File</button></div> | ||||||
| 							<div><button onclick="removeFile()">Remove File</button></div> | 							<div><button id="remove_file_button">Remove File</button></div> | ||||||
| 						</div> | 						</div> | ||||||
| 					</div> | 					</div> | ||||||
| 					<div id="docPane" style="display: flex; flex: 1 1 50%; flex-flow: column"> | 					<div id="docPane" style="display: flex; flex: 1 1 50%; flex-flow: column"> | ||||||
| @@ -62,6 +62,6 @@ | |||||||
| 		</div> | 		</div> | ||||||
| 		<script src="/split/split.min.js"></script> | 		<script src="/split/split.min.js"></script> | ||||||
| 		<script src="/smoothie/smoothie.js"></script> | 		<script src="/smoothie/smoothie.js"></script> | ||||||
| 		<script src="/static/client.js"></script> | 		<script src="/static/client.js" type="module"></script> | ||||||
| 	</body> | 	</body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user