diff --git a/node_modules/proxysocket/LICENSE.md b/node_modules/proxysocket/LICENSE.md new file mode 100644 index 0000000..5e501d0 --- /dev/null +++ b/node_modules/proxysocket/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Kristopher Ives + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/proxysocket/README.md b/node_modules/proxysocket/README.md new file mode 100644 index 0000000..63dcaa9 --- /dev/null +++ b/node_modules/proxysocket/README.md @@ -0,0 +1,108 @@ +# proxysocket + +[![Join the chat at https://gitter.im/krisives/proxysocket](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/krisives/proxysocket?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +`proxysocket` is a nodejs module for seamlessly making socket connections via a +SOCKS5 proxy. Use it in place of a regular `net.Socket` to easily talk over +Tor or an SSH tunnel. + +## Install + +Available on npm for easy install: + + npm install proxysocket + +You can also download a [release](https://github.com/krisives/proxysocket/releases) manually and +extract it as `proxysocket` has no dependencies. + +## Usage + +Because `proxysocket` provides the same API as a regular `net.Socket` object +you can use it in many places where sockets and streams are used. + +### Making a Socket + +Create a new socket that will use the proxy: + + var proxysocket = require('proxysocket'); + var socket = proxysocket.create('localhost', 9050); + +The returned object behaves like an ordinary `net.Socket` object. +For example, you can call `connect()` or listen for events: + + socket.connect('website.com', 80, function () { + // Connected + }); + + socket.on('data', function (data) { + // Receive data + }); + +Also note if you're using Tor it's fine to pass `.onion` hosts: + + socket.connect('p4fsi4ockecnea7l.onion', 6667); + + +### Making HTTP Requests + +You can use `proxysocket.createAgent()` to create an object +like `http.Agent` which will make proxy sockets for you when using +`http.request()`. Here is an example: + + var proxysocket = require('proxysocket'); + var http = require('http'); + var agent = proxysocket.createAgent(); + + http.request({ + host: 'foo.com', + agent: agent + }); + + +## API + +### proxysocket.create(socksHost, socksPort, socket) + +Create a new socket object that uses a SOCKS5 proxy provided. + +* `socksHost` is the host of the proxy. Default is `localhost` +* `socksPort` is the port of the proxy. Default is `9050` +* `socket` can be an existing `net.Socket` object. Default is a `new Socket()` + +### proxysocket.createAgent(socksHost, socksPort) + +Returns an object like `http.Agent` which makes new sockets +using `proxysocket.create()` as needed. + +### socket + +The object returned from `proxysocket.create()` is just like a regular +`net.Socket`. This documentation lists additions to the API. + +*Note This documentation doesn't list all of the methods, properties, +or events of `net.Socket`, `Readable` or `Writable`. See the nodejs +API reference for those modules.* + +### socket.socksHost + +Get the host address of the proxy. By default this will be `localhost`. + +### socket.socksPort + +Get the port of the proxy. By default this will be `9050`. + +### socket.realSocket + +Get the underlying raw `net.Socket` connection to the proxy. You don't need +to use this and instead should listen on `this` socket instead. + +### socket 'socksdata' event + +`socksdata` is emitted whenever underlying data is received from the proxy +before the socket is ready for use. This is mainly here for debugging and you +should use the `data` event instead. + +## Contributing + +Please fork and make a pull request if you have anything cool to add. You're +also welcome to join the [Gitter](https://gitter.im/krisives/proxysocket?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) chat. diff --git a/node_modules/proxysocket/package.json b/node_modules/proxysocket/package.json new file mode 100644 index 0000000..f75384b --- /dev/null +++ b/node_modules/proxysocket/package.json @@ -0,0 +1,91 @@ +{ + "_args": [ + [ + "proxysocket", + "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client" + ] + ], + "_from": "proxysocket@latest", + "_id": "proxysocket@1.2.0", + "_inCache": true, + "_installable": true, + "_location": "/proxysocket", + "_nodeVersion": "4.6.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/proxysocket-1.2.0.tgz_1477420117142_0.21117400820367038" + }, + "_npmUser": { + "email": "kristopher.ives@gmail.com", + "name": "krisives" + }, + "_npmVersion": "2.15.9", + "_phantomChildren": {}, + "_requested": { + "name": "proxysocket", + "raw": "proxysocket", + "rawSpec": "", + "scope": null, + "spec": "latest", + "type": "tag" + }, + "_requiredBy": [ + "#USER" + ], + "_resolved": "https://registry.npmjs.org/proxysocket/-/proxysocket-1.2.0.tgz", + "_shasum": "0d654c36754a40421e7e65971d62fe1f1a6938b7", + "_shrinkwrap": null, + "_spec": "proxysocket", + "_where": "/mnt/c/Users/Josua/Desktop/data/nodejs/electron/chat-project/chat-client", + "author": { + "email": "kristopher.ives@gmail.com", + "name": "Kristopher Ives", + "url": "https://github.com/krisives" + }, + "bugs": { + "url": "https://github.com/krisives/proxysocket/issues" + }, + "dependencies": {}, + "description": "SOCKS5 client for making socket connections", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "0d654c36754a40421e7e65971d62fe1f1a6938b7", + "tarball": "https://registry.npmjs.org/proxysocket/-/proxysocket-1.2.0.tgz" + }, + "engines": { + "node": "0.x" + }, + "gitHead": "156f6fa27313979126a9743ec0ec9cab21fc8915", + "homepage": "https://github.com/krisives/proxysocket", + "keywords": [ + "proxy", + "socket", + "socks", + "socks4", + "socks5", + "tor" + ], + "licenses": [ + { + "type": "MIT", + "url": "http://mattcg.mit-license.org/" + } + ], + "main": "proxysocket.js", + "maintainers": [ + { + "name": "krisives", + "email": "kristopher.ives@gmail.com" + } + ], + "name": "proxysocket", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/krisives/proxysocket.git" + }, + "scripts": {}, + "version": "1.2.0" +} diff --git a/node_modules/proxysocket/proxysocket.js b/node_modules/proxysocket/proxysocket.js new file mode 100644 index 0000000..176ef82 --- /dev/null +++ b/node_modules/proxysocket/proxysocket.js @@ -0,0 +1,459 @@ + + +var net = require('net'); +var EventEmitter = require('events').EventEmitter; +var inherits = require('util').inherits; + +function proxysocket(socksHost, socksPort, socket) { + var self = this; + + // Set when we start connect() + var connecting = false; + + // Set when connection stages are finished + var connected = false; + + // Stages in the SOCKS5 connection + var connectionStages = [ + receiveSocksAuth, + receiveSocksConnect + ]; + + // What stage we are in currently + var stage = 0; + + // Set from connect() to what host and port we are connecting to + var host = '', port = 0; + + // While the SOCKS connection is going we buffer the + // requests to write() + var unsent = []; + // and to pipe() + var unpiped = []; + + // While the socket is still being setup the encoding + // is saved as we expect binray encoding on the socket + // until then + var socketEncoding = null; + + // Default host/ports to use if not given + self.socksHost = socksHost = socksHost || 'localhost'; + self.socksPort = socksPort = socksPort || '9050'; + + // Users can pass their own socket if they already have one + // connected to the SOCKS proxy + self.realSocket = socket = socket || (new net.Socket({ + readable: true, + writable: true + })); + + // A socket emits events like 'data' and 'connect' + EventEmitter.call(self); + + self.readable = true; + self.writable = true; + + // Read event for the real socket + socket.on('data', function (buffer) { + if (connected) { + self.emit('data', buffer); + } else { + // Emit an event useful for debugging the raw SOCKS data + self.emit('socksdata', buffer); + + // Handle SOCKS protocol data + receiveSocksData(buffer); + } + }); + + socket.on('error', function (e) { + self.emit('error', e); + }); + + socket.on('end', function () { + self.writable = false; + + self.emit('end'); + }); + + socket.on('timeout', function () { + self.emit('timeout'); + }); + + socket.on('close', function () { + self.writable = false; + + if (connected) { + self.emit('close'); + } + }); + + socket.on('drain', function () { + if (connected) { + self.emit('drain'); + } + }); + + socket.on('readable', function () { + if (connected) { + self.emit('readable'); + } + }); + + self.read = function (size) { + if (!connected) { + return null; + } + + return socket.read(size); + }; + + self.destroy = function () { + self.writable = false; + + return socket.destroy(); + }; + + self.destroySoon = function () { + self.writable = false; + + return socket.destroySoon(); + }; + + self.ref = function () { + return socket.ref(); + }; + + self.unref = function () { + return socket.unref(); + }; + + self.setKeepAlive = function (enable, initialDelay) { + return socket.setKeepAlive(enable, initialDelay); + }; + + self.pipe = function (dest, opts) { + if (connected) { + return socket.pipe(dest, opts); + } + + unpiped.push([dest, opts]); + return dest; + }; + + // Handle SOCKS protocol specific data + function receiveSocksData(data) { + while (data && stage < connectionStages.length) { + data = connectionStages[stage](data); + stage++; + } + + // Emit the sockets first packet + if (connected && data) { + self.emit('data', data); + } + } + + // Handle the response after sending authentication + function receiveSocksAuth(d) { + var error; + + if (d.length !== 2) { + error = new Error('SOCKS authentication failed. Unexpected number of bytes received.'); + } else if (d[0] !== 0x05) { + error = new Error('SOCKS authentication failed. Unexpected SOCKS version number: ' + d[0] + '.'); + } else if (d[1] !== 0x00) { + error = new Error('SOCKS authentication failed. Unexpected SOCKS authentication method: ' + d[1] + '.'); + } + + if (error) { + self.emit('error', error); + return; + } + + sendConnect(); + } + + // Handle the response after sending connection request + function receiveSocksConnect(d) { + var error; + + if (d[0] !== 0x05) { + error = new Error('SOCKS connection failed. Unexpected SOCKS version number: ' + d[0] + '.'); + } else if (d[1] !== 0x00) { + error = new Error('SOCKS connection failed. ' + connectErrors[d[1]] + '.'); + } else if (d[2] !== 0x00) { + error = new Error('SOCKS connection failed. The reserved byte must be 0x00.'); + } + + if (error) { + self.emit('error', error); + return; + } + + connected = true; + + // TODO map some of the addresses? + self.localPort = socket.localPort; + self.localAddress = socket.localAddress; + self.remotePort = socket.remotePort; + self.remoteAddress = socket.remoteAddress; + self.bufferSize = socket.bufferSize; + + // Set the real encoding which could have been + // changed while the socket was connecting + setEncoding(socketEncoding); + + if (unsent.length) { + for (var i=0; i < unsent.length; i++) { + socket.write(unsent[i][0], unsent[i][1], unsent[i][2]); + } + + unsent = []; + } + + if (unpiped.length) { + for (var i=0; i < unpiped.length; i++) { + socket.pipe(unpiped[i][0], unpiped[i][1]); + } + + unpiped = []; + } + + // Emit the real 'connect' event + self.emit('connect'); + } + + function sendAuth() { + var request = new Buffer(3); + request[0] = 0x05; // SOCKS version + request[1] = 0x01; // number of authentication methods + request[2] = 0x00; // no authentication + + if (!socket.write(request)) { + throw new Error("Unable to write to SOCKS socket"); + } + } + + // Parse a domain name into a buffer + function parseDomainName(host, buffer) { + var i, c; + + buffer.push(host.length); + + for (i = 0; i < host.length; i++) { + c = host.charCodeAt(i); + buffer.push(c); + } + } + + // Parse an host like 1.2.3.4 into a 32-bit number + function parseIPv4(host, buffer) { + var i, n; + var parts = host.split('.'); + + for (i = 0; i < parts.length; ++i) { + n = parseInt(parts[i], 10); + buffer.push(n); + } + } + + // Parse a IPv6 host into a buffer + function parseIPv6(host, buffer) { + var parts = host.split(':'); + var i, ind; + var zeros = []; + + parts[0] = parts[0] || '0000'; + parts[parts.length - 1] = parts[parts.length - 1] || '0000'; + ind = parts.indexOf(''); + + if (ind >= 0) { + for (i = 0; i < 8 - parts.length + 1; ++i) { + zeros.push('0000'); + } + + parts = parts.slice(0, ind).concat(zeros).concat(parts.slice(ind + 1)); + } + + for (i = 0; i < 8; ++i) { + var num = parseInt(parts[i], 16); + buffer.push(num / 256 | 0); + buffer.push(num % 256); + } + } + + function sendConnect() { + var request; + var buffer = [ + 0x05, // SOCKS version + 0x01, // Command code: establish a TCP/IP stream connection + 0x00 // Reserved - myst be 0x00 + ]; + + switch (net.isIP(host)) { + default: + case 0: + buffer.push(0x03); + parseDomainName(host, buffer); + break; + case 4: + buffer.push(0x01); + parseIPv4(host, buffer); + break; + case 6: + buffer.push(0x04); + parseIPv6(host, buffer); + break; + } + + htons(buffer, buffer.length, port); + request = new Buffer(buffer); + + if (!socket.write(request)) { + throw new Error("Unable to write to SOCKS socket"); + } + } + + self.setTimeout = function (timeout, f) { + return socket.setTimeout(timeout, f); + }; + + self.setNoDelay = function (noDelay) { + return socket.setNoDelay(noDelay); + }; + + self.connect = function (connectHost, connectPort, f) { + if (connected) { + throw new Error("Socket is already connected"); + } + + if (connecting) { + throw new Error("Socket is already connecting"); + } + + host = connectHost; + port = connectPort; + connected = false; + connecting = true; + + if (f) { + self.on('connect', f); + } + + setEncoding(null); + + socket.connect(socksPort, socksHost, function () { + connecting = false; + sendAuth(); + }); + }; + + self.write = function (data, encoding, f) { + if (!connected) { + unsent.push([data, encoding, f]); + return; + } + + return socket.write(data, encoding, f); + }; + + self.pause = function () { + socket.pause(); + }; + + self.resume = function () { + socket.resume(); + }; + + self.address = function () { + return socket.address(); + }; + + self.end = function (data, encoding) { + socket.writable = false; + + if (!connected) { + return socket.end(); + } + + return socket.end(data, encoding); + }; + + self.setEncoding = function (encoding) { + if (connected) { + setEncoding(encoding); + } else { + // Save encoding to be set once connected + socketEncoding = encoding; + } + }; + + function setEncoding(enc) { + if (enc === null) { + // Accroding to nodejs documentation, readable.setEncoding(null) + // is a way to disable encoding. + // However, it's not. So, need to hack into readable structure. + socket.decoder = null; + socket.encoding = null; + } else { + socket.setEncoding(enc); + } + } + + return self; +} + +inherits(proxysocket, EventEmitter); + +proxysocket.create = function (socksHost, socksPort, socket) { + return new proxysocket(socksHost, socksPort, socket); +}; + +// A simple agent so that requests can be made using http.request() +// and anything else using the same Agent API +proxysocket.createAgent = function (socksHost, socksPort) { + var http = require('http'); + + var agent = new http.Agent({ + // keepAlive: true + }); + + function connect(host, port, f) { + var socket = proxysocket.create(socksHost, socksPort); + socket.connect(host, port, f); + return socket; + } + + agent.createConnection = function (options, f) { + return connect( + options.host, + options.port, + f + ); + }; + + return agent; +}; + +module.exports = proxysocket; + +// Converts a 16-bit short from Host To Network Storage +function htons(b, i, v) { + b[i] = (0xff & (v >> 8)); + b[i + 1] = (0xff & (v)); +} + +// Error messages for when the proxy responds to sendConnect() used in handleConnect() +var connectErrors = { + // Messages are taken from Wikipedia + 0x00: 'request granted', + 0x01: 'general failure', + 0x02: 'connection not allowed by ruleset', + 0x03: 'network unreachable', + 0x04: 'host unreachable', + 0x05: 'connection refused by destination host', + 0x06: 'TTL expired', + 0x07: 'command not supported / protocol error', + 0x08: 'address type not supported' +}; diff --git a/node_modules/showdown/package.json b/node_modules/showdown/package.json index 7f9a3b5..5b5c683 100644 --- a/node_modules/showdown/package.json +++ b/node_modules/showdown/package.json @@ -49,10 +49,10 @@ }, "contributors": [ { - "name": "Cat Chen" + "name": "John Fraser" }, { - "name": "John Gruber" + "name": "Cat Chen" }, { "name": "Corey Innis" @@ -70,7 +70,7 @@ "name": "Dominic Tarr" }, { - "name": "John Fraser" + "name": "John Gruber" }, { "name": "Titus Stone" diff --git a/style.css b/style.css index b4929d4..b5bc82b 100644 --- a/style.css +++ b/style.css @@ -104,3 +104,7 @@ .chat-content-message.sender div { background-color: #AAE; } + +.chat-content-message p { + word-break: break-all; +}