From 2a56a32475ce23ec69d4a0a2c1a3d21990b82cff Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Jul 2015 11:42:19 -0500 Subject: [PATCH] add blob and file http servers; add open file to menu --- app/index.js | 11 ++++++++--- app/lib/blobs.js | 38 ++++++++++++++++++++++++++++++++++++++ app/lib/files.js | 32 ++++++++++++++++++++++++++++++++ app/lib/menu.js | 15 +++++++++++++++ app/lib/muxrpc-ipc.js | 6 +++++- app/lib/windows.js | 18 ++++++++++++++++-- package.json | 2 +- 7 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 app/lib/files.js diff --git a/app/index.js b/app/index.js index 672fcce..9a45e2d 100644 --- a/app/index.js +++ b/app/index.js @@ -1,6 +1,7 @@ var app = require('app') var Menu = require('menu') var path = require('path') +var http = require('http') var config = require('ssb-config') var windows = require('./lib/windows') @@ -14,14 +15,18 @@ app.on('ready', function ready () { // register sbot plugins sbot.use(require('phoenix-api')) - // setup electron + // setup blob and file serving var blobs = require('./lib/blobs')(sbot, app.getPath('userDesktop')) require('protocol').registerProtocol('blob', blobs.protocol) + http.createServer(blobs.server).listen(7777) + http.createServer(require('./lib/files').server).listen(7778) + + // open main window var mainWindow = windows.open( - 'file://' + path.join(__dirname, '../node_modules/ssbplug-phoenix/home.html'), + 'file://' + path.join(__dirname, '../node_modules/ssbplug-phoenix/main.html'), sbot, blobs, - { width: 1000, height: 720 } + { width: 1030, height: 720 } ) require('./lib/menu')(mainWindow) // mainWindow.openDevTools() diff --git a/app/lib/blobs.js b/app/lib/blobs.js index cd9aa46..185737d 100644 --- a/app/lib/blobs.js +++ b/app/lib/blobs.js @@ -69,6 +69,44 @@ module.exports = function (sbot, checkout_dir) { cb = null } }) + }, + + server: function (req, res) { + // function toBuffer() { + // return pull.map(function (s) { return Buffer.isBuffer(s) ? s : new Buffer(s, 'base64') }) + // } + + // local-host only + if (req.socket.remoteAddress != '127.0.0.1' && + req.socket.remoteAddress != '::ffff:127.0.0.1' && + req.socket.remoteAddress != '::1') { + console.log('Remote access attempted by', req.socket.remoteAddress) + res.writeHead(403) + return res.end('Remote access forbidden') + } + + // restrict the CSP + res.setHeader('Content-Security-Policy', + "default-src 'self' 'unsafe-inline' 'unsafe-eval' data:; "+ + "connect-src 'self'; "+ + "object-src 'none'; "+ + "frame-src 'none'; "+ + "sandbox allow-same-origin allow-scripts" + ) + + var hash = req.url.slice(1) + sbot.blobs.has(hash, function(err, has) { + if (!has) { + res.writeHead(404) + res.end('File not found') + return + } + pull( + sbot.blobs.get(hash), + // toBuffer(), + toPull(res) + ) + }) } } diff --git a/app/lib/files.js b/app/lib/files.js new file mode 100644 index 0000000..cb543c8 --- /dev/null +++ b/app/lib/files.js @@ -0,0 +1,32 @@ +var path = require('path') +var fs = require('fs') + +exports.server = function (req, res) { + // function toBuffer() { + // return pull.map(function (s) { return Buffer.isBuffer(s) ? s : new Buffer(s, 'base64') }) + // } + // local-host only + if (req.socket.remoteAddress != '127.0.0.1' && + req.socket.remoteAddress != '::ffff:127.0.0.1' && + req.socket.remoteAddress != '::1') { + console.log('Remote access attempted by', req.socket.remoteAddress) + res.writeHead(403) + return res.end('Remote access forbidden') + } + + // restrict the CSP + res.setHeader('Content-Security-Policy', + "default-src 'self' localhost:7777 'unsafe-inline' 'unsafe-eval' data:; "+ + "connect-src 'self'; "+ + "object-src 'none'; "+ + "frame-src 'none'; "+ + "sandbox allow-same-origin allow-scripts" + ) + + fs.createReadStream(req.url) + .on('error', function () { + res.writeHead(404) + res.end('File not found') + }) + .pipe(res) +} \ No newline at end of file diff --git a/app/lib/menu.js b/app/lib/menu.js index a7f583c..9ad8d6c 100644 --- a/app/lib/menu.js +++ b/app/lib/menu.js @@ -1,4 +1,5 @@ var Menu = require('menu') +var dialog = require('dialog') module.exports = function (window) { var template = [ @@ -19,6 +20,20 @@ module.exports = function (window) { } ] }, + { + label: 'File', + submenu: [ + { + label: 'Open File...', + accelerator: 'Command+O', + click: function() { + var paths = dialog.showOpenDialog(window, { properties: ['openFile'] }) + if (paths && paths[0]) + window.rpc.navigate(paths[0]) + } + } + ] + }, { label: 'Edit', submenu: [ diff --git a/app/lib/muxrpc-ipc.js b/app/lib/muxrpc-ipc.js index 4836916..bf87790 100644 --- a/app/lib/muxrpc-ipc.js +++ b/app/lib/muxrpc-ipc.js @@ -4,6 +4,10 @@ var pull = require('pull-stream') var pushable = require('pull-pushable') var Api = require('scuttlebot/lib/api') +var clientApi = { + navigate: 'async' +} + module.exports = function (window, sbot, params) { // construct api var api = Api(sbot) @@ -16,7 +20,7 @@ module.exports = function (window, sbot, params) { // add rpc APIs to window window.createRpc = function () { // create rpc object - var rpc = window.rpc = muxrpc(null, sbot.manifest, serialize)(api) + var rpc = window.rpc = muxrpc(clientApi, sbot.manifest, serialize)(api) rpc.authorized = { id: sbot.feed.id, role: 'master' } rpc.permissions({allow: null, deny: null}) function serialize (stream) { return stream } diff --git a/app/lib/windows.js b/app/lib/windows.js index 81778ee..deee9db 100644 --- a/app/lib/windows.js +++ b/app/lib/windows.js @@ -6,11 +6,25 @@ var blobslib = require('./blobs') var windows = [] +var secureWebPreferences = { + javascript: true, + 'web-security': true, + images: true, + java: false, + webgl: false, // maybe allow? + webaudio: false, // maybe allow? + plugins: false, + 'experimental-features': false, + 'experimental-canvas-features': false, + 'shared-worker': false +} + var open = module.exports.open = function (url, sbot, blobs, opts, params) { var win = new BrowserWindow(opts) win.loadUrl(url) setupRpc(win, sbot, params) + windows.push(win) win.on('closed', function() { var i = windows.indexOf(win) @@ -35,13 +49,13 @@ module.exports.open = function (url, sbot, blobs, opts, params) { 'file://' + path.join(__dirname, '../../node_modules/ssbplug-phoenix/blob-search.html'), sbot, blobs, - { width: 600, height: 650 }, + { width: 600, height: 650, 'web-preferences': secureWebPreferences }, { url: url, hash: hash } ) } else console.log(err) // :TODO: something nicer } else { - shell.openItem(filepath) + shell.openItem(filepath) // open in desktop's default program } }) } else { diff --git a/package.json b/package.json index 4bead5e..e441786 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "multiblob": "^1.5.0", "multicb": "^1.1.0", "muxrpc": "^5.0.1", - "phoenix-api": "~8.2.0", + "phoenix-api": "~8.3.0", "pull-pushable": "^1.1.4", "pull-stream": "^2.27.0", "scuttlebot": "^4.2.3",