more endpoints reimplemented in new api
This commit is contained in:
parent
a148826b39
commit
0b38f78a64
102
onionr/api.py
102
onionr/api.py
@ -64,19 +64,99 @@ class PublicAPI:
|
|||||||
self.i2pEnabled = config.get('i2p.host', False)
|
self.i2pEnabled = config.get('i2p.host', False)
|
||||||
self.hideBlocks = [] # Blocks to be denied sharing
|
self.hideBlocks = [] # Blocks to be denied sharing
|
||||||
self.host = setBindIP(clientAPI._core.publicApiHostFile)
|
self.host = setBindIP(clientAPI._core.publicApiHostFile)
|
||||||
bindPort = config.get('client.public.port')
|
self.torAdder = clientAPI._core.hsAddress
|
||||||
|
self.i2pAdder = clientAPI._core.i2pAddress
|
||||||
|
self.bindPort = config.get('client.public.port')
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def validateRequest():
|
||||||
|
'''Validate request has the correct hostname'''
|
||||||
|
if type(self.torAdder) is None and type(self.i2pAdder) is None:
|
||||||
|
# abort if our hs addresses are not known
|
||||||
|
abort(403)
|
||||||
|
if request.host not in (self.i2pAdder, self.torAdder):
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
@app.after_request
|
||||||
|
def sendHeaders(resp):
|
||||||
|
'''Send api, access control headers'''
|
||||||
|
resp.headers['Date'] = 'Thu, 1 Jan 1970 00:00:00 GMT' # Clock info is probably useful to attackers. Set to unix epoch.
|
||||||
|
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['X-Frame-Options'] = 'deny'
|
||||||
|
resp.headers['X-Content-Type-Options'] = "nosniff"
|
||||||
|
resp.headers['X-API'] = API_VERSION
|
||||||
|
return resp
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def banner():
|
def banner():
|
||||||
#validateHost('public')
|
|
||||||
try:
|
try:
|
||||||
with open('static-data/index.html', 'r') as html:
|
with open('static-data/index.html', 'r') as html:
|
||||||
resp = Response(html.read(), mimetype='text/html')
|
resp = Response(html.read(), mimetype='text/html')
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
resp = Response("")
|
resp = Response("")
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@app.route('/getblocklist')
|
||||||
|
def getBlockList():
|
||||||
|
bList = clientAPI._core.getBlockList()
|
||||||
|
for b in self.hideBlocks:
|
||||||
|
if b in bList:
|
||||||
|
bList.remove(b)
|
||||||
|
return Response('\n'.join(bList))
|
||||||
|
|
||||||
|
@app.route('/getdata/<name>')
|
||||||
|
def getBlockData():
|
||||||
|
resp = ''
|
||||||
|
if clientAPI._utils.validateHash(data):
|
||||||
|
if data not in self.hideBlocks:
|
||||||
|
if os.path.exists(clientAPI._core.dataDir + 'blocks/' + data + '.dat'):
|
||||||
|
block = Block(hash=data.encode(), core=clientAPI._core)
|
||||||
|
resp = base64.b64encode(block.getRaw().encode()).decode()
|
||||||
|
if len(resp) == 0:
|
||||||
|
abort(404)
|
||||||
|
resp = ""
|
||||||
|
return Response(resp)
|
||||||
|
|
||||||
|
@app.route('/ping')
|
||||||
|
def ping():
|
||||||
|
return Response("pong!")
|
||||||
|
|
||||||
|
@app.route('/getdbhash')
|
||||||
|
def getDBHash():
|
||||||
|
return Response(clientAPI._utils.getBlockDBHash())
|
||||||
|
|
||||||
|
@app.route('/pex')
|
||||||
|
def peerExchange():
|
||||||
|
response = ','.join(self._core.listAdders())
|
||||||
|
if len(response) == 0:
|
||||||
|
response = 'none'
|
||||||
|
resp = Response(response)
|
||||||
|
|
||||||
|
@app.route('/upload', methods=['post'])
|
||||||
|
def upload():
|
||||||
|
resp = 'failure'
|
||||||
|
try:
|
||||||
|
data = request.form['block']
|
||||||
|
except KeyError:
|
||||||
|
logger.warn('No block specified for upload')
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if sys.getsizeof(data) < 100000000:
|
||||||
|
try:
|
||||||
|
if blockimporter.importBlockFromData(data, clientAPI._core):
|
||||||
|
resp = 'success'
|
||||||
|
else:
|
||||||
|
logger.warn('Error encountered importing uploaded block')
|
||||||
|
except onionrexceptions.BlacklistedBlock:
|
||||||
|
logger.debug('uploaded block is blacklisted')
|
||||||
|
pass
|
||||||
|
if resp == 'failure':
|
||||||
|
abort(400)
|
||||||
|
resp = Response(resp)
|
||||||
|
return resp
|
||||||
|
|
||||||
clientAPI.setPublicAPIInstance(self)
|
clientAPI.setPublicAPIInstance(self)
|
||||||
self.httpServer = WSGIServer((self.host, bindPort), app, log=None)
|
self.httpServer = WSGIServer((self.host, self.bindPort), app, log=None)
|
||||||
self.httpServer.serve_forever()
|
self.httpServer.serve_forever()
|
||||||
|
|
||||||
class API:
|
class API:
|
||||||
@ -144,7 +224,21 @@ class API:
|
|||||||
def hello():
|
def hello():
|
||||||
return Response("hello client")
|
return Response("hello client")
|
||||||
|
|
||||||
@app.route('/waitforshare/<name>', methods='post')
|
@app.route('/site/<name>')
|
||||||
|
def site():
|
||||||
|
bHash = block
|
||||||
|
resp = 'Not Found'
|
||||||
|
if self._core._utils.validateHash(bHash):
|
||||||
|
resp = Block(bHash).bcontent
|
||||||
|
try:
|
||||||
|
resp = base64.b64decode(resp)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if resp == 'Not Found':
|
||||||
|
abourt(404)
|
||||||
|
return Response(resp)
|
||||||
|
|
||||||
|
@app.route('/waitforshare/<name>', methods=['post'])
|
||||||
def waitforshare():
|
def waitforshare():
|
||||||
assert name.isalnum()
|
assert name.isalnum()
|
||||||
if name in self.publicAPI.hideBlocks:
|
if name in self.publicAPI.hideBlocks:
|
||||||
|
@ -180,14 +180,14 @@ class OnionrCommunicatorDaemon:
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
newDBHash = self.peerAction(peer, 'getDBHash') # get their db hash
|
newDBHash = self.peerAction(peer, 'getdbhash') # get their db hash
|
||||||
if newDBHash == False or not self._core._utils.validateHash(newDBHash):
|
if newDBHash == False or not self._core._utils.validateHash(newDBHash):
|
||||||
continue # if request failed, restart loop (peer is added to offline peers automatically)
|
continue # if request failed, restart loop (peer is added to offline peers automatically)
|
||||||
triedPeers.append(peer)
|
triedPeers.append(peer)
|
||||||
if newDBHash != self._core.getAddressInfo(peer, 'DBHash'):
|
if newDBHash != self._core.getAddressInfo(peer, 'DBHash'):
|
||||||
self._core.setAddressInfo(peer, 'DBHash', newDBHash)
|
self._core.setAddressInfo(peer, 'DBHash', newDBHash)
|
||||||
try:
|
try:
|
||||||
newBlocks = self.peerAction(peer, 'getBlockHashes') # get list of new block hashes
|
newBlocks = self.peerAction(peer, 'getblocklist') # get list of new block hashes
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.warn('Could not get new blocks from %s.' % peer, error = error)
|
logger.warn('Could not get new blocks from %s.' % peer, error = error)
|
||||||
newBlocks = False
|
newBlocks = False
|
||||||
@ -226,7 +226,7 @@ class OnionrCommunicatorDaemon:
|
|||||||
self.currentDownloading.append(blockHash) # So we can avoid concurrent downloading in other threads of same block
|
self.currentDownloading.append(blockHash) # So we can avoid concurrent downloading in other threads of same block
|
||||||
logger.info("Attempting to download %s..." % blockHash)
|
logger.info("Attempting to download %s..." % blockHash)
|
||||||
peerUsed = self.pickOnlinePeer()
|
peerUsed = self.pickOnlinePeer()
|
||||||
content = self.peerAction(peerUsed, 'getData', data=blockHash) # block content from random peer (includes metadata)
|
content = self.peerAction(peerUsed, 'getdata/' + blockHash) # block content from random peer (includes metadata)
|
||||||
if content != False and len(content) > 0:
|
if content != False and len(content) > 0:
|
||||||
try:
|
try:
|
||||||
content = content.encode()
|
content = content.encode()
|
||||||
@ -423,7 +423,7 @@ class OnionrCommunicatorDaemon:
|
|||||||
if len(peer) == 0:
|
if len(peer) == 0:
|
||||||
return False
|
return False
|
||||||
#logger.debug('Performing ' + action + ' with ' + peer + ' on port ' + str(self.proxyPort))
|
#logger.debug('Performing ' + action + ' with ' + peer + ' on port ' + str(self.proxyPort))
|
||||||
url = 'http://' + peer + '/public/?action=' + action
|
url = 'http://' + peer + '/' + action
|
||||||
if len(data) > 0:
|
if len(data) > 0:
|
||||||
url += '&data=' + data
|
url += '&data=' + data
|
||||||
|
|
||||||
@ -520,7 +520,7 @@ class OnionrCommunicatorDaemon:
|
|||||||
if peer in triedPeers:
|
if peer in triedPeers:
|
||||||
continue
|
continue
|
||||||
triedPeers.append(peer)
|
triedPeers.append(peer)
|
||||||
url = 'http://' + peer + '/public/upload/'
|
url = 'http://' + peer + '/upload'
|
||||||
data = {'block': block.Block(bl).getRaw()}
|
data = {'block': block.Block(bl).getRaw()}
|
||||||
proxyType = ''
|
proxyType = ''
|
||||||
if peer.endswith('.onion'):
|
if peer.endswith('.onion'):
|
||||||
@ -529,7 +529,7 @@ class OnionrCommunicatorDaemon:
|
|||||||
proxyType = 'i2p'
|
proxyType = 'i2p'
|
||||||
logger.info("Uploading block to " + peer)
|
logger.info("Uploading block to " + peer)
|
||||||
if not self._core._utils.doPostRequest(url, data=data, proxyType=proxyType) == False:
|
if not self._core._utils.doPostRequest(url, data=data, proxyType=proxyType) == False:
|
||||||
self._core._utils.localCommand('waitForShare', data=bl)
|
self._core._utils.localCommand('waitforshare/' + bl)
|
||||||
finishedUploads.append(bl)
|
finishedUploads.append(bl)
|
||||||
break
|
break
|
||||||
for x in finishedUploads:
|
for x in finishedUploads:
|
||||||
|
@ -53,6 +53,7 @@ class Core:
|
|||||||
self.privateApiHostFile = self.dataDir + 'private-host.txt'
|
self.privateApiHostFile = self.dataDir + 'private-host.txt'
|
||||||
self.addressDB = self.dataDir + 'address.db'
|
self.addressDB = self.dataDir + 'address.db'
|
||||||
self.hsAddress = ''
|
self.hsAddress = ''
|
||||||
|
self.i2pAddress = config.get('i2p.ownAddr', None)
|
||||||
self.bootstrapFileLocation = 'static-data/bootstrap-nodes.txt'
|
self.bootstrapFileLocation = 'static-data/bootstrap-nodes.txt'
|
||||||
self.bootstrapList = []
|
self.bootstrapList = []
|
||||||
self.requirements = onionrvalues.OnionrValues()
|
self.requirements = onionrvalues.OnionrValues()
|
||||||
@ -775,7 +776,7 @@ class Core:
|
|||||||
if payload != False:
|
if payload != False:
|
||||||
retData = self.setData(payload)
|
retData = self.setData(payload)
|
||||||
# Tell the api server through localCommand to wait for the daemon to upload this block to make stastical analysis more difficult
|
# Tell the api server through localCommand to wait for the daemon to upload this block to make stastical analysis more difficult
|
||||||
self._utils.localCommand('waitForShare', data=retData)
|
self._utils.localCommand('waitforshare/' + retData)
|
||||||
self.addToBlockDB(retData, selfInsert=True, dataSaved=True)
|
self.addToBlockDB(retData, selfInsert=True, dataSaved=True)
|
||||||
#self.setBlockType(retData, meta['type'])
|
#self.setBlockType(retData, meta['type'])
|
||||||
self._utils.processBlockMetadata(retData)
|
self._utils.processBlockMetadata(retData)
|
||||||
|
Loading…
Reference in New Issue
Block a user