Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TorBot GUI #152

Merged
merged 37 commits into from
Dec 7, 2018
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d69ade6
Adding front-end architecture
KingAkeem Nov 11, 2018
cfdb4c3
fixing titles
KingAkeem Nov 11, 2018
e055ab1
Adding eslint to hound
KingAkeem Nov 11, 2018
d43521a
Fixing syntax
KingAkeem Nov 11, 2018
81a3316
Removing buildJ
KingAkeem Nov 11, 2018
6d54348
Remvoing build and setting title
KingAkeem Nov 11, 2018
e119490
Setting up WS Server for front end
KingAkeem Nov 12, 2018
d52b5a6
Adding input and button
KingAkeem Nov 12, 2018
30b82d7
Successful WSMessages!
KingAkeem Nov 12, 2018
d725b11
Adding ability to use Onion links as well
KingAkeem Nov 12, 2018
06ef3be
Code cleanup
KingAkeem Nov 12, 2018
36f0f86
Adding support for onion
KingAkeem Nov 12, 2018
941e8fe
Adding onion button
KingAkeem Nov 12, 2018
66b1376
More styling, fixing WS latency issue
KingAkeem Nov 12, 2018
2a08689
Rendering links from TorBot
KingAkeem Nov 12, 2018
dc5636b
Removing useless enumeration
KingAkeem Nov 12, 2018
540e68e
Adding home button
KingAkeem Nov 12, 2018
a143d36
Merge branch 'dev' into front_end
KingAkeem Nov 16, 2018
9bbe784
Sending node links, updating function to class attribute
KingAkeem Nov 16, 2018
0c14198
Adding documentation
KingAkeem Nov 17, 2018
d8c42f8
Adding error checking for incorrect URLs
KingAkeem Nov 17, 2018
f994c3c
Returning after error, no need to render page
KingAkeem Nov 17, 2018
31ba103
Organizing file structure
KingAkeem Nov 17, 2018
f5a3b14
Async urls for websocket, results in better performance and smoother …
KingAkeem Nov 17, 2018
9b1ff79
Adding proxy head and actually displaying status of link
KingAkeem Nov 18, 2018
200917d
Cleaning up code
KingAkeem Nov 18, 2018
85cc2aa
Moving WebSocket to links
KingAkeem Nov 18, 2018
9265007
Adding documentation
KingAkeem Nov 18, 2018
aa70a9a
Disabling jshint
KingAkeem Nov 18, 2018
43dd359
Adding documentation
KingAkeem Nov 18, 2018
1989da5
Minor refactor
KingAkeem Nov 18, 2018
622a931
pylint and hound
KingAkeem Nov 18, 2018
54515e9
Renaming file
KingAkeem Nov 18, 2018
71594bf
Getting paste event to capture initial paste
KingAkeem Nov 18, 2018
e9032c7
Adding radio buttons for action selection
KingAkeem Nov 18, 2018
e33e272
Beginning work on get_info feature
KingAkeem Nov 18, 2018
fcf739d
Adding loading screen and renaming folder
KingAkeem Nov 24, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
File renamed without changes.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ modules/.pytest_cache
modules/.ropeproject/
modules/lib/*.so

# JS Ignores
node_modules
build

# Tests Ignores
tests/.pytest_cache
tests/*.pyc
Expand Down
5 changes: 4 additions & 1 deletion .hound.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
flake8:
enabled: true
enabled: true
eslint:
enbaled: true
config_file: ./ui/.eslintrc.json
File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions dev/run_server.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
if [ -f ../torBot.py ]; then
python3 ../torBot.py --server
fi
if [ -f torBot.py ]; then
python3 torBot.py --server
fi
14 changes: 7 additions & 7 deletions modules/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from bs4 import BeautifulSoup
from .utils import multi_thread
from .color import color
from .proxy import proxyGET

def get_emails(node):
"""Finds all emails associated with node
Expand Down Expand Up @@ -54,8 +55,7 @@ class LinkNode:
link (str): link to be used as node
"""

def __init__(self, link):
# If link has invalid form, throw an error
def __init__(self, link, *, tor=True, tld=False):
if not self.valid_link(link):
raise ValueError("Invalid link format.")

Expand All @@ -65,11 +65,11 @@ def __init__(self, link):

# Attempts to connect to link, throws an error if link is unreachable
try:
self.response = requests.get(link)
except (requests.exceptions.ChunkedEncodingError,
requests.exceptions.HTTPError,
requests.exceptions.ConnectionError,
ConnectionError) as err:
if tor:
self.response = proxyGET(link)
else:
self.response = requests.get(link)
except (requests.exceptions.ChunkedEncodingError, requests.exceptions.HTTPError, requests.exceptions.ConnectionError, ConnectionError) as err:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (150 > 79 characters)

raise err

self._node = BeautifulSoup(self.response.text, 'html.parser')
Expand Down
22 changes: 22 additions & 0 deletions modules/proxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import requests

proxies = {
'http': 'socks5h://localhost:9050',
'https': 'socks5h://localhost:9050'
}

session = requests.session()
session.proxies = proxies

def proxyGET(url, headers=None):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 0

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

if headers:
return session.get(url, headers=headers)
else:
return session.get(url)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line at end of file

def proxyHEAD(url, timeout=10, headers=None):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

if headers:
return session.head(url, timeout=timeout, headers=headers)
else:
return session.head(url, timeout=timeout)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line at end of file

6 changes: 3 additions & 3 deletions modules/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from threading import Thread
from requests.exceptions import HTTPError
import requests

from .proxy import proxyGET

# ALGORITHM UTILITY FUNCTIONS

Expand Down Expand Up @@ -77,9 +77,9 @@ def get_url_status(url, headers=False):
"""
try:
if headers:
resp = requests.get(url, headers=headers)
resp = proxyGET(url, headers)
else:
resp = requests.get(url)
resp = proxyGET(url)
resp.raise_for_status()
return resp
except (ConnectionError, HTTPError):
Expand Down
93 changes: 93 additions & 0 deletions modules/wsserver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""
Module contains WebSocket server
"""

# Built-in Imports
import asyncio
import json
import logging

# Third Party Imports
import tldextract
import websockets
import requests
from bs4 import BeautifulSoup

# Local Imports
from .link import LinkNode
from .proxy import proxyGET, proxyHEAD


# Setting up logging format
# Logs include {time} {loglevel} {logmessage}
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.INFO,
datefmt='%Y-%m-%d %H:%M:%S')

async def handle_msg(websocket, path):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 0

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

"""
Handles incoming WebSocket messages from front-end.
The appropriate action is taken based on the message.

Args:
websocket (websockets.protocol): websocket connection being used
path (string): contains origin of websocket message
"""
msg = await websocket.recv()
data = json.loads(msg) # Load JSON response from front-end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least two spaces before inline comment

url = data['url']
# action determines what we will do with the url
action = data['action']
if action == 'get_links':
async for link in get_links(websocket, url):
response = json.dumps(link)
await websocket.send(response)

async def get_links(websocket, url):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

"""
Get links from url

Args:
url (string): url to get links from
Returns:
links (list): list containing links
"""
ext = tldextract.extract(url)
tor = ext.domain == 'onion' or ext.suffix == 'onion'

# If there's an error with the url then we return it to be logged and sent
try:
if tor:
response = proxyGET(url)
else:
response = requests.get(url)
except Exception as err:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace

yield {'name': url, 'status': False, 'error': str(err)}
return

soup = BeautifulSoup(response.text, 'html.parser')
anchor_tags = soup.find_all('a')
links = list()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local variable 'links' is assigned to but never used

for anchor in anchor_tags:
link = anchor.get('href')
if link and LinkNode.valid_link(link):

try:
# Returns true if status_code is less than 400, false if not
if tor:
status = proxyHEAD(link, timeout=5).ok
else:
status = requests.head(link, timeout=5).ok
yield {'name': link, 'status': status}
except Exception as err:
yield {'name': link, 'status': False, 'error': str(err)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace


def start_wsserver():
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

"""
Starts WebSocketServer
"""
print('Starting WSServer on address localhost:8080')
start_server = websockets.serve(handle_msg, 'localhost', '8080')
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ pyinstaller==3.4.0
ete3==3.1.1
PyQt5==5.11.3
validators==0.12.2
websockets==7.0.0
tldextract==2.2.0
51 changes: 9 additions & 42 deletions torBot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
MAIN MODULE
"""
import argparse
import socket
import socks

from requests.exceptions import HTTPError

Expand All @@ -14,6 +12,7 @@
from modules.updater import updateTor
from modules.savefile import saveJson
from modules.info import execute_all
from modules.wsserver import start_wsserver

# GLOBAL CONSTS
LOCALHOST = "127.0.0.1"
Expand All @@ -22,45 +21,6 @@
# TorBot VERSION
__VERSION = "1.3.1"


def connect(address, port):
""" Establishes connection to port

Assumes port is bound to localhost, if host that port is bound to changes
then change the port

Args:
address: address for port to bound to
port: Establishes connect to this port
"""

if address and port:
socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, address, port)
elif address:
socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, address, DEFPORT)
elif port:
socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, LOCALHOST, port)
else:
socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, LOCALHOST, DEFPORT)

socket.socket = socks.socksocket # Monkey Patch our socket to tor socket

def getaddrinfo(*args):
"""
Overloads socket function for std socket library
Check socket.getaddrinfo() documentation to understand parameters.
Simple description below:
argument - explanation (actual value)
socket.AF_INET - the type of address the socket can speak to (IPV4)
sock.SOCK_STREAM - creates a stream connecton rather than packets
6 - protocol being used is TCP
Last two arguments should be a tuple containing the address and port
"""
return [(socket.AF_INET, socket.SOCK_STREAM, 6,
'', (args[0], args[1]))]
socket.getaddrinfo = getaddrinfo


def header():
"""
Prints out header ASCII art
Expand Down Expand Up @@ -118,6 +78,8 @@ def get_args():
help="Visualizes tree of data gathered.")
parser.add_argument("-d", "--download", action="store_true",
help="Downloads tree of data gathered.")
parser.add_argument("--server", action="store_true",
help="Start TorBot WebSocket server.")
return parser.parse_args()


Expand All @@ -126,7 +88,8 @@ def main():
TorBot's Core
"""
args = get_args()
connect(args.ip, args.port)
if args.server:
start_wsserver()

# If flag is -v, --update, -q/--quiet then user only runs that operation
# because these are single flags only
Expand All @@ -138,6 +101,10 @@ def main():
exit()
if not args.quiet:
header()
try:
node = LinkNode(args.url, tld=args.extension)
except (ValueError, HTTPError, ConnectionError) as err:
raise err
# If url flag is set then check for accompanying flag set. Only one
# additional flag can be set with -u/--url flag
if args.url:
Expand Down
33 changes: 33 additions & 0 deletions ui/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"env": {
"node": true,
"browser": true,
"commonjs": true,
"es6": true
},
"extends": ["plugin:react/recommended","eslint:recommended"],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}
44 changes: 44 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "torbot",
"version": "0.1.0",
"private": true,
"dependencies": {
"electron-reload-webpack-plugin": "^2.0.4",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"react-scripts": "2.0.5"
},
"scripts": {
"start": "webpack --mode development --watch",
"build": "webpack --mode production",
"test": "react-scripts test",
"eject": "react-scripts eject",
"electron": "electron ."
},
"homepage": "./",
"main": "src/electron-main.js",
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"@babel/preset-env": "^7.1.0",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"css-loader": "^1.0.1",
"electron": "^3.0.8",
"electron-connect": "^0.6.3",
"electron-reload": "^1.2.5",
"eslint": "^5.9.0",
"eslint-config-prettier": "^3.3.0",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-react": "^7.11.1",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.4",
"prettier": "^1.15.2",
"webpack-cli": "^3.1.2"
}
}
Empty file added ui/src/app.css
Empty file.
15 changes: 15 additions & 0 deletions ui/src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'import' is only available in ES6 (use 'esversion: 6').

import Home from './components/home';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'import' is only available in ES6 (use 'esversion: 6').

import './app.css';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'import' is only available in ES6 (use 'esversion: 6').


/**
* Entrypoint for TorBot app, displays home-page
* @class App
*/
class App extends React.Component {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'class' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

render() {
return <Home/>;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expected an assignment or function call and instead saw an expression.
Expected an identifier and instead saw '<'.
Expected an identifier and instead saw '>'.
Missing semicolon.

}
}

export default App;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'export' is only available in ES6 (use 'esversion: 6').