started a simple board plugin
parent
b45bb94375
commit
2289171b0f
|
@ -1,6 +0,0 @@
|
||||||
test:
|
|
||||||
script:
|
|
||||||
- apt-get update -qy
|
|
||||||
- apt-get install -y python3-dev python3-pip tor
|
|
||||||
- pip3 install -r requirements.txt
|
|
||||||
- make test
|
|
|
@ -1,8 +0,0 @@
|
||||||
language: python
|
|
||||||
python:
|
|
||||||
- "3.6.4"
|
|
||||||
# install dependencies
|
|
||||||
install:
|
|
||||||
- sudo apt install tor
|
|
||||||
- pip install -r requirements.txt
|
|
||||||
script: make test
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/sh
|
||||||
|
nohup ./run-linux start & disown
|
|
@ -17,7 +17,7 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
'''
|
||||||
import flask
|
import flask, cgi
|
||||||
from flask import request, Response, abort, send_from_directory
|
from flask import request, Response, abort, send_from_directory
|
||||||
from gevent.pywsgi import WSGIServer
|
from gevent.pywsgi import WSGIServer
|
||||||
import sys, random, threading, hmac, hashlib, base64, time, math, os, json
|
import sys, random, threading, hmac, hashlib, base64, time, math, os, json
|
||||||
|
@ -221,7 +221,8 @@ class API:
|
||||||
This initilization defines all of the API entry points and handlers for the endpoints and errors
|
This initilization defines all of the API entry points and handlers for the endpoints and errors
|
||||||
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
||||||
'''
|
'''
|
||||||
|
# assert isinstance(onionrInst, onionr.Onionr)
|
||||||
|
print(type(onionrInst))
|
||||||
# configure logger and stuff
|
# configure logger and stuff
|
||||||
onionr.Onionr.setupConfig('data/', self = self)
|
onionr.Onionr.setupConfig('data/', self = self)
|
||||||
|
|
||||||
|
@ -234,6 +235,8 @@ class API:
|
||||||
bindPort = int(config.get('client.client.port', 59496))
|
bindPort = int(config.get('client.client.port', 59496))
|
||||||
self.bindPort = bindPort
|
self.bindPort = bindPort
|
||||||
|
|
||||||
|
self.whitelistEndpoints = ('site', 'www', 'onionrhome', 'board', 'boardContent')
|
||||||
|
|
||||||
self.clientToken = config.get('client.webpassword')
|
self.clientToken = config.get('client.webpassword')
|
||||||
self.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
|
self.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
|
||||||
|
|
||||||
|
@ -249,6 +252,8 @@ class API:
|
||||||
'''Validate request has set password and is the correct hostname'''
|
'''Validate request has set password and is the correct hostname'''
|
||||||
if request.host != '%s:%s' % (self.host, self.bindPort):
|
if request.host != '%s:%s' % (self.host, self.bindPort):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
if request.endpoint in self.whitelistEndpoints:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
if not hmac.compare_digest(request.headers['token'], self.clientToken):
|
if not hmac.compare_digest(request.headers['token'], self.clientToken):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
@ -257,7 +262,8 @@ class API:
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def afterReq(resp):
|
def afterReq(resp):
|
||||||
resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
#resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
||||||
|
resp.headers['Content-Security-Policy'] = "default-src 'none'; script-src 'self'; object-src 'none'; style-src 'self'; img-src 'self'; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'self'"
|
||||||
resp.headers['X-Frame-Options'] = 'deny'
|
resp.headers['X-Frame-Options'] = 'deny'
|
||||||
resp.headers['X-Content-Type-Options'] = "nosniff"
|
resp.headers['X-Content-Type-Options'] = "nosniff"
|
||||||
resp.headers['X-API'] = onionr.API_VERSION
|
resp.headers['X-API'] = onionr.API_VERSION
|
||||||
|
@ -265,20 +271,54 @@ class API:
|
||||||
resp.headers['Date'] = 'Thu, 1 Jan 1970 00:00:00 GMT' # Clock info is probably useful to attackers. Set to unix epoch.
|
resp.headers['Date'] = 'Thu, 1 Jan 1970 00:00:00 GMT' # Clock info is probably useful to attackers. Set to unix epoch.
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@app.route('/board/', endpoint='board')
|
||||||
|
def loadBoard():
|
||||||
|
return send_from_directory('static-data/www/board/', "index.html")
|
||||||
|
|
||||||
|
@app.route('/board/<path:path>', endpoint='boardContent')
|
||||||
|
def boardContent(path):
|
||||||
|
return send_from_directory('static-data/www/board/', path)
|
||||||
|
|
||||||
|
@app.route('/www/<path:path>', endpoint='www')
|
||||||
|
def wwwPublic(path):
|
||||||
|
if not config.get("www.private.run", True):
|
||||||
|
abort(403)
|
||||||
|
return send_from_directory(config.get('www.private.path', 'static-data/www/private/'), path)
|
||||||
|
|
||||||
@app.route('/ping')
|
@app.route('/ping')
|
||||||
def ping():
|
def ping():
|
||||||
return Response("pong!")
|
return Response("pong!")
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/', endpoint='onionrhome')
|
||||||
def hello():
|
def hello():
|
||||||
return Response("hello client")
|
return Response("Welcome to Onionr")
|
||||||
|
|
||||||
|
@app.route('/getblocksbytype/<name>')
|
||||||
|
def getBlocksByType(name):
|
||||||
|
blocks = self._core.getBlocksByType(name)
|
||||||
|
return Response(','.join(blocks))
|
||||||
|
|
||||||
|
@app.route('/gethtmlsafeblockdata/<name>')
|
||||||
|
def getData(name):
|
||||||
|
resp = ''
|
||||||
|
if self._core._utils.validateHash(name):
|
||||||
|
try:
|
||||||
|
resp = cgi.escape(Block(name).bcontent, quote=True)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
abort(404)
|
||||||
|
return Response(resp)
|
||||||
|
|
||||||
@app.route('/site/<name>')
|
@app.route('/site/<name>', endpoint='site')
|
||||||
def site():
|
def site(name):
|
||||||
bHash = block
|
bHash = name
|
||||||
resp = 'Not Found'
|
resp = 'Not Found'
|
||||||
if self._core._utils.validateHash(bHash):
|
if self._core._utils.validateHash(bHash):
|
||||||
resp = Block(bHash).bcontent
|
try:
|
||||||
|
resp = Block(bHash).bcontent
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
resp = base64.b64decode(resp)
|
resp = base64.b64decode(resp)
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -268,7 +268,7 @@ class OnionrCrypto:
|
||||||
blockHash = blockHash.decode() # bytes on some versions for some reason
|
blockHash = blockHash.decode() # bytes on some versions for some reason
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent, ourBlock=False)
|
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent, ourBlock=False)
|
||||||
|
|
||||||
if difficulty < int(config.get('general.minimum_block_pow')):
|
if difficulty < int(config.get('general.minimum_block_pow')):
|
||||||
|
|
|
@ -57,6 +57,8 @@ def getDifficultyForNewBlock(data, ourBlock=True):
|
||||||
dataSize = len(data.getRaw().encode('utf-8'))
|
dataSize = len(data.getRaw().encode('utf-8'))
|
||||||
elif isinstance(data, str):
|
elif isinstance(data, str):
|
||||||
dataSize = len(data.encode('utf-8'))
|
dataSize = len(data.encode('utf-8'))
|
||||||
|
elif isinstance(data, bytes):
|
||||||
|
dataSize = len(data)
|
||||||
elif isinstance(data, int):
|
elif isinstance(data, int):
|
||||||
dataSize = data
|
dataSize = data
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
"general" : {
|
"general" : {
|
||||||
"dev_mode" : true,
|
"dev_mode" : true,
|
||||||
"display_header" : false,
|
"display_header" : false,
|
||||||
"minimum_block_pow": 4,
|
"minimum_block_pow": 3,
|
||||||
"minimum_send_pow": 4,
|
"minimum_send_pow": 3,
|
||||||
"socket_servers": false,
|
"socket_servers": false,
|
||||||
"security_level": 0,
|
"security_level": 0,
|
||||||
"max_block_age": 2678400,
|
"max_block_age": 2678400,
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
"allocations" : {
|
"allocations" : {
|
||||||
"disk" : 2000,
|
"disk" : 100000000,
|
||||||
"net_total" : 1000000000,
|
"net_total" : 1000000000,
|
||||||
"blockCache" : 5000000,
|
"blockCache" : 5000000,
|
||||||
"blockCacheTotal" : 50000000
|
"blockCacheTotal" : 50000000
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
webpassword = ''
|
||||||
|
requested = {}
|
||||||
|
document.getElementById('feed').innerText = 'none :)'
|
||||||
|
|
||||||
|
function httpGet(theUrl) {
|
||||||
|
var xmlHttp = new XMLHttpRequest()
|
||||||
|
xmlHttp.open( "GET", theUrl, false ) // false for synchronous request
|
||||||
|
xmlHttp.setRequestHeader('token', webpassword)
|
||||||
|
xmlHttp.send( null )
|
||||||
|
return xmlHttp.responseText
|
||||||
|
}
|
||||||
|
function appendMessages(msg){
|
||||||
|
document.getElementById('feed').append(msg)
|
||||||
|
document.getElementById('feed').appendChild(document.createElement('br'))
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlocks(){
|
||||||
|
var feedText = httpGet('/getblocksbytype/txt')
|
||||||
|
var blockList = feedText.split(',')
|
||||||
|
for (i = 0; i < blockList.length; i++){
|
||||||
|
bl = httpGet('/gethtmlsafeblockdata/' + blockList[i])
|
||||||
|
appendMessages(bl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('webpassword').oninput = function(){
|
||||||
|
webpassword = document.getElementById('webpassword').value
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('refreshFeed').onclick = function(){
|
||||||
|
getBlocks()
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<title>
|
||||||
|
OnionrBoard
|
||||||
|
</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Onionr Board</h1>
|
||||||
|
<input id='webpassword' type='password' placeholder="Web password for daemon">
|
||||||
|
<input type='button' id='refreshFeed' value='Refresh Feed'>
|
||||||
|
<div id='feed'></div>
|
||||||
|
<script src='board.js'></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue