diff --git a/extension.js b/extension.js index 0977ed6..d2bc6a4 100644 --- a/extension.js +++ b/extension.js @@ -1,115 +1,19 @@ // ex: set sw=4 'use strict'; -const Gio = imports.gi.Gio; const Lang = imports.lang; const St = imports.gi.St; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const TorControlClient = Me.imports.tor_control_client.TorControlClient; + const TorIcon = 'tor'; let torButton; let torControlClient; -const TorControlClient = new Lang.Class({ - Name: 'TorControlClient', - - _init: function() { - this._connect(); - this._updateProtocolInfo(); - this._ensureProtocolCompatibility(); - }, - - close: function() { - this._outputStream.close(null); - this._inputStream.close(null); - }, - - _connect: function() { - this._socketClient = new Gio.SocketClient(); - this._connection = this._socketClient.connect_to_host('127.0.0.1:9051', null, null); - this._inputStream = new Gio.DataInputStream({base_stream: this._connection.get_input_stream()}); - this._outputStream = new Gio.DataOutputStream({base_stream: this._connection.get_output_stream()}); - }, - - _updateProtocolInfo: function() { - var reply = this._runCommand('PROTOCOLINFO'); - - if (reply.statusCode != 250) { - throw "Could not read protocol info"; - } - - var protocolInfoVersion; - var authMethods = []; - var authCookieFile; - - for (let i = 0; i < reply.replyLines.length; i++) { - let tokens = reply.replyLines[i].split(' '); - - switch (tokens[0]) { - case 'PROTOCOLINFO': - protocolInfoVersion = tokens[1]; - break; - case 'AUTH': - let methodsArg = tokens[1].split('='); - authMethods = methodsArg[1].split(','); - - if (authMethods.indexOf('COOKIE') != -1 || authMethods.indexOf('SAFECOOKIE') != -1) { - let cookieArg = tokens[2].split('='); - authCookieFile = cookieArg[1]; - } - break; - } - } - - this._protocolInfo = { - protocolInfoVersion: protocolInfoVersion, - authMethods: authMethods, - authCookieFile: authCookieFile - } - }, - - _ensureProtocolCompatibility: function() { - if (this._protocolInfo.protocolInfoVersion != 1) { - throw 'Cannot handle tor protocol version ' + this._protocolInfo.protocolInfoVersion; - } - }, - - _runCommand: function(cmd) { - this._outputStream.put_string(cmd + '\n', null); - this._outputStream.flush(null); - - var statusCode; - var replyLines = []; - - do { - let line = this._readLine(); - var reply = this._parseLine(line); - - statusCode = reply.statusCode; - replyLines.push(reply.replyLine); - } while (reply.isMidReplyLine); - - return { - statusCode: statusCode, - replyLines: replyLines - } - }, - - _readLine: function() { - return this._inputStream.read_line(null, null)[0].toString().trim(); - }, - - _parseLine: function(line) { - return { - statusCode: parseInt(line.substr(0, 3)), - isMidReplyLine: (line[3] == '-'), - replyLine: line.substring(4) - } - } -}); - const TorButton = new Lang.Class({ Name: 'TorButton', Extends: PanelMenu.Button, diff --git a/tor_control_client.js b/tor_control_client.js new file mode 100644 index 0000000..fc0f4ea --- /dev/null +++ b/tor_control_client.js @@ -0,0 +1,104 @@ +// ex: set sw=4 +'use strict'; + +const Gio = imports.gi.Gio; +const Lang = imports.lang; + +const TorControlClient = new Lang.Class({ + Name: 'TorControlClient', + + _init: function() { + this._connect(); + this._updateProtocolInfo(); + this._ensureProtocolCompatibility(); + }, + + close: function() { + this._outputStream.close(null); + this._inputStream.close(null); + }, + + _connect: function() { + var socketClient = new Gio.SocketClient(); + var connection = socketClient.connect_to_host('127.0.0.1:9051', null, null); + this._inputStream = new Gio.DataInputStream({base_stream: connection.get_input_stream()}); + this._outputStream = new Gio.DataOutputStream({base_stream: connection.get_output_stream()}); + }, + + _updateProtocolInfo: function() { + var reply = this._runCommand('PROTOCOLINFO'); + + if (reply.statusCode != 250) { + throw "Could not read protocol info"; + } + + var protocolInfoVersion; + var authMethods = []; + var authCookieFile; + + for (let i = 0; i < reply.replyLines.length; i++) { + let tokens = reply.replyLines[i].split(' '); + + switch (tokens[0]) { + case 'PROTOCOLINFO': + protocolInfoVersion = tokens[1]; + break; + case 'AUTH': + let methodsArg = tokens[1].split('='); + authMethods = methodsArg[1].split(','); + + if (authMethods.indexOf('COOKIE') != -1 || authMethods.indexOf('SAFECOOKIE') != -1) { + let cookieArg = tokens[2].split('='); + authCookieFile = cookieArg[1]; + } + break; + } + } + + this._protocolInfo = { + protocolInfoVersion: protocolInfoVersion, + authMethods: authMethods, + authCookieFile: authCookieFile + } + }, + + _ensureProtocolCompatibility: function() { + if (this._protocolInfo.protocolInfoVersion != 1) { + throw 'Cannot handle tor protocol version ' + this._protocolInfo.protocolInfoVersion; + } + }, + + _runCommand: function(cmd) { + this._outputStream.put_string(cmd + '\n', null); + this._outputStream.flush(null); + + var statusCode; + var replyLines = []; + + do { + let line = this._readLine(); + var reply = this._parseLine(line); + + statusCode = reply.statusCode; + replyLines.push(reply.replyLine); + } while (reply.isMidReplyLine); + + return { + statusCode: statusCode, + replyLines: replyLines + } + }, + + _readLine: function() { + return this._inputStream.read_line(null, null)[0].toString().trim(); + }, + + _parseLine: function(line) { + return { + statusCode: parseInt(line.substr(0, 3)), + isMidReplyLine: (line[3] == '-'), + replyLine: line.substring(4) + } + } +}); +