Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit fb58f5a5c3e1886efcac0c06bf06207b799040d2 @mikeal committed Feb 27, 2012
Showing with 188 additions and 0 deletions.
  1. +49 −0 README.mkd
  2. +30 −0 client.js
  3. +77 −0 index.js
  4. +13 −0 package.json
  5. +19 −0 test.html
@@ -0,0 +1,49 @@
+# siofile - read files over socket.io
+
+## server
+
+```javascript
+ var siofile = require('siofile')
+
+ io.sockets.on('connection', function (socket) {
+ socket.on('siofile', siofile(socket))
+ })
+```
+
+This is **incredibly** insecure because it allows all clients access to your entire filesystem.
+
+Instead.
+
+```javascript
+ socket.on('siofile', siofile(socket, '/home/me/myfile'))
+```
+
+Or you can give a list of files you want to make available.
+
+```javascript
+ socket.on('siofile', siofile(socket, ['/home/me/myfile1', '/home/me/myfile2']))
+```
+
+## browser
+
+```html
+ <script src="/socket.io/socket.io.js"></script>
+ <script>
+ var socket = io.connect('http://localhost')
+
+ socket.on('connect', function () {
+ siofile(socket).read('/home/me/myfile', function (err, data) {
+ console.log(err, data)
+ })
+ })
+
+ </script>
+```
+
+Alternatively, you can also *watch* a file, which will first read the contents and then call your callback again every time new data is appended to the file. This is ideal for watching log files.
+
+```javascript
+ siofile(socket).watch('/home/me/myfile', function (err, data) {
+ console.log(err, data)
+ })
+```
@@ -0,0 +1,30 @@
+window.siofile = function siofile (socket) {
+ var sessions = {}
+ , exports = {}
+ ;
+ exports.read = function (opts, cb) {
+ if (typeof opts === 'string') opts = {file:opts}
+ opts.session = Math.floor(Math.random()*1111111111)
+ sessions[opts.session] = cb
+ socket.emit('siofile', opts)
+ }
+ exports.watch = function (opts, cb) {
+ if (typeof opts === 'string') opts = {file:opts}
+ opts.session = Math.floor(Math.random()*1111111111)
+ opts.watch = true
+ sessions[opts.session] = cb
+ socket.emit('siofile', opts)
+ }
+
+ socket.on('siofile-stat', function (obj) {
+ if (obj.error) sessions[obj.session](obj.error)
+ })
+ socket.on('siofile-read', function (obj) {
+ if (!sessions[obj.session]) {
+ throw new Error('No session with id = '+obj.session)
+ }
+ sessions[obj.session](null, obj.data)
+ })
+
+ return exports
+}
@@ -0,0 +1,77 @@
+var fs = require('fs')
+ , path = require('path')
+ ;
+
+module.exports = function (socket, files) {
+ if (typeof files === 'string') files = [files]
+ if (!files) console.error('WARNING! You are allowing access to all your files.')
+ function siofile (opts) {
+ var file = opts.file
+ , session = opts.session
+ , offset = opts.offset || 0
+ , size = opts.size || null
+ , watch = opts.watch || false
+ , interval = opts.interval || 500
+ , disconnected = false
+ ;
+ if (files && files.indexOf(file) === -1) {
+ return socket.emit('siofile-stat', {error:'Security Error. File not allowed.', session:session})
+ }
+ socket.on('disconnect', function () {
+ disconnected = true
+ })
+ fs.stat(file, function (err, stat) {
+ if (disconnected) return
+ socket.emit('siofile-stat', {session:session, error:err, stat:stat})
+ if (err) return
+
+ function readchunk (offset, size) {
+ fs.open(file, 'r', function (err, fd) {
+ if (disconnected) return
+ if (err) return socket.emit('siofile-stat', {session:session, error:err, stat:stat})
+ if (size === null) {
+ size = stat.size
+ }
+ if (offset < 0) {
+ offset = stat.size + offset
+ }
+
+ var b = new Buffer(size)
+ fs.read(fd, b, 0, size, offset, function (e) {
+ if (disconnected) return
+ if (e) return socket.emit('siofile-stat', {session:session, error:err, stat:stat})
+ socket.emit('siofile-read', {session:session, data:b.toString()})
+ if (watch) {
+ function check () {
+ fs.stat(file, function (e, s) {
+ if (s.size > stat.size) {
+ readchunk(stat.size, s.size - stat.size)
+ stat = s
+ } else {
+ setTimeout(check, interval)
+ }
+ })
+ }
+ setTimeout(check, interval)
+ }
+ })
+ })
+ }
+ readchunk(offset, size)
+ })
+ }
+ return siofile
+}
+
+// var app = require('http').createServer(function (req, resp) {
+// if (req.url === '/siofile.js') return require('filed')('client.js').pipe(resp)
+// require('filed')('test.html').pipe(resp)
+// })
+// , io = require('socket.io').listen(app)
+// ;
+//
+// app.listen(8000)
+//
+// io.sockets.on('connection', function (socket) {
+// socket.on('siofile', module.exports(socket))
+// })
@@ -0,0 +1,13 @@
+{
+ "author": "Mikeal Rogers <mikeal.rogers@gmail.com> (http://www.mikealrogers.com)",
+ "name": "siofile",
+ "description": "Stream a file to a socket.io client.",
+ "version": "0.0.0",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/mikeal/siofile.git"
+ },
+ "main": "index.js",
+ "dependencies": {},
+ "devDependencies": {}
+}
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <script src="/socket.io/socket.io.js"></script>
+ <script src="/siofile.js"></script>
+ <script>
+ var socket = io.connect('http://localhost:8000')
+
+ socket.on('connect', function () {
+ siofile(socket).watch('index.js', function (err, data) {
+ console.log(err, data)
+ })
+ })
+
+ </script>
+</head>
+<body>
+
+</body>
+<html>

0 comments on commit fb58f5a

Please sign in to comment.