2020-04-04 11:00:19 +00:00
|
|
|
__filename__ = "session.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
|
|
|
__version__ = "1.1.0"
|
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
__email__ = "bob@freedombone.net"
|
|
|
|
__status__ = "Production"
|
2019-06-28 18:55:29 +00:00
|
|
|
|
2019-07-16 14:23:06 +00:00
|
|
|
import os
|
2019-06-28 18:55:29 +00:00
|
|
|
import requests
|
2019-07-02 10:39:55 +00:00
|
|
|
from utils import urlPermitted
|
2019-06-28 18:55:29 +00:00
|
|
|
import json
|
2020-06-23 13:28:41 +00:00
|
|
|
from socket import error as SocketError
|
|
|
|
import errno
|
2019-06-28 18:55:29 +00:00
|
|
|
|
2020-04-04 11:00:19 +00:00
|
|
|
baseDirectory = None
|
|
|
|
|
2019-06-30 18:23:18 +00:00
|
|
|
|
2020-06-09 11:03:59 +00:00
|
|
|
def createSession(proxyType: str):
|
2020-06-08 17:10:53 +00:00
|
|
|
session = None
|
|
|
|
try:
|
2020-06-23 22:15:55 +00:00
|
|
|
session = requests.session(config={'keep_alive': True})
|
2020-06-23 21:39:19 +00:00
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
print('WARN: requests error during createSession')
|
2020-06-23 13:41:12 +00:00
|
|
|
print(e)
|
|
|
|
return None
|
2020-06-23 13:28:41 +00:00
|
|
|
except SocketError as e:
|
|
|
|
if e.errno == errno.ECONNRESET:
|
|
|
|
print('WARN: connection was reset during createSession')
|
|
|
|
else:
|
2020-06-23 13:41:12 +00:00
|
|
|
print('WARN: socket error during createSession')
|
|
|
|
print(e)
|
2020-06-08 17:10:53 +00:00
|
|
|
return None
|
2020-06-23 21:39:19 +00:00
|
|
|
except ValueError as e:
|
|
|
|
print('WARN: error during createSession')
|
|
|
|
print(e)
|
|
|
|
return None
|
2020-06-09 11:03:59 +00:00
|
|
|
if not session:
|
|
|
|
return None
|
|
|
|
if proxyType == 'tor':
|
2020-04-04 11:00:19 +00:00
|
|
|
session.proxies = {}
|
|
|
|
session.proxies['http'] = 'socks5h://localhost:9050'
|
|
|
|
session.proxies['https'] = 'socks5h://localhost:9050'
|
2020-06-09 11:03:59 +00:00
|
|
|
elif proxyType == 'i2p':
|
|
|
|
session.proxies = {}
|
2020-06-19 22:09:20 +00:00
|
|
|
session.proxies['http'] = 'socks5h://localhost:4447'
|
|
|
|
session.proxies['https'] = 'socks5h://localhost:4447'
|
2020-06-09 11:51:51 +00:00
|
|
|
elif proxyType == 'gnunet':
|
|
|
|
session.proxies = {}
|
|
|
|
session.proxies['http'] = 'socks5h://localhost:7777'
|
|
|
|
session.proxies['https'] = 'socks5h://localhost:7777'
|
2019-06-28 18:55:29 +00:00
|
|
|
return session
|
|
|
|
|
2020-04-04 11:00:19 +00:00
|
|
|
|
|
|
|
def getJson(session, url: str, headers: {}, params: {},
|
|
|
|
version='1.0.0', httpPrefix='https',
|
|
|
|
domain='testdomain') -> {}:
|
2019-09-01 13:13:52 +00:00
|
|
|
if not isinstance(url, str):
|
2020-04-04 11:00:19 +00:00
|
|
|
print('url: ' + str(url))
|
2019-09-01 13:13:52 +00:00
|
|
|
print('ERROR: getJson url should be a string')
|
|
|
|
return None
|
2020-04-04 11:00:19 +00:00
|
|
|
sessionParams = {}
|
|
|
|
sessionHeaders = {}
|
2019-06-28 18:55:29 +00:00
|
|
|
if headers:
|
2020-04-04 11:00:19 +00:00
|
|
|
sessionHeaders = headers
|
2019-06-28 18:55:29 +00:00
|
|
|
if params:
|
2020-04-04 11:00:19 +00:00
|
|
|
sessionParams = params
|
|
|
|
sessionHeaders['User-Agent'] = 'Epicyon/' + version
|
2019-08-26 14:08:41 +00:00
|
|
|
if domain:
|
2020-04-04 11:00:19 +00:00
|
|
|
sessionHeaders['User-Agent'] += \
|
|
|
|
'; +' + httpPrefix + '://' + domain + '/'
|
2019-07-16 10:19:04 +00:00
|
|
|
if not session:
|
|
|
|
print('WARN: no session specified for getJson')
|
2019-07-04 17:31:41 +00:00
|
|
|
try:
|
2020-04-04 11:00:19 +00:00
|
|
|
result = session.get(url, headers=sessionHeaders, params=sessionParams)
|
2019-07-04 17:31:41 +00:00
|
|
|
return result.json()
|
2020-06-23 21:39:19 +00:00
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
print('ERROR: getJson failed\nurl: ' + str(url) + '\n' +
|
|
|
|
'headers: ' + str(sessionHeaders) + '\n' +
|
|
|
|
'params: ' + str(sessionParams) + '\n')
|
|
|
|
print(e)
|
2020-06-23 13:41:12 +00:00
|
|
|
except ValueError as e:
|
2020-06-08 18:05:36 +00:00
|
|
|
print('ERROR: getJson failed\nurl: ' + str(url) + '\n' +
|
|
|
|
'headers: ' + str(sessionHeaders) + '\n' +
|
2020-06-09 11:51:51 +00:00
|
|
|
'params: ' + str(sessionParams) + '\n')
|
2019-08-14 22:24:51 +00:00
|
|
|
print(e)
|
2020-06-23 13:41:12 +00:00
|
|
|
except SocketError as e:
|
|
|
|
if e.errno == errno.ECONNRESET:
|
|
|
|
print('WARN: connection was reset during getJson')
|
|
|
|
print(e)
|
2019-07-04 17:31:41 +00:00
|
|
|
return None
|
2019-06-28 19:36:39 +00:00
|
|
|
|
2020-04-04 11:00:19 +00:00
|
|
|
|
|
|
|
def postJson(session, postJsonObject: {}, federationList: [],
|
|
|
|
inboxUrl: str, headers: {}, capability: str) -> str:
|
2019-06-28 19:36:39 +00:00
|
|
|
"""Post a json message to the inbox of another person
|
2019-07-06 11:03:51 +00:00
|
|
|
Supplying a capability, such as "inbox:write"
|
2019-06-28 19:36:39 +00:00
|
|
|
"""
|
2019-07-06 11:03:51 +00:00
|
|
|
# always allow capability requests
|
2020-03-22 21:16:02 +00:00
|
|
|
if not capability.startswith('cap'):
|
2019-07-06 11:03:51 +00:00
|
|
|
# check that we are posting to a permitted domain
|
2020-04-04 11:00:19 +00:00
|
|
|
if not urlPermitted(inboxUrl, federationList, capability):
|
|
|
|
print('postJson: ' + inboxUrl + ' not permitted')
|
2019-07-06 11:03:51 +00:00
|
|
|
return None
|
2019-06-28 20:22:36 +00:00
|
|
|
|
2020-06-08 18:05:36 +00:00
|
|
|
try:
|
|
|
|
postResult = \
|
|
|
|
session.post(url=inboxUrl,
|
|
|
|
data=json.dumps(postJsonObject),
|
|
|
|
headers=headers)
|
2020-06-23 21:39:19 +00:00
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
print('ERROR: postJson requests failed ' + inboxUrl + ' ' +
|
2020-06-23 13:41:12 +00:00
|
|
|
json.dumps(postJsonObject) + ' ' + str(headers))
|
|
|
|
print(e)
|
|
|
|
return None
|
2020-06-23 13:28:41 +00:00
|
|
|
except SocketError as e:
|
|
|
|
if e.errno == errno.ECONNRESET:
|
|
|
|
print('WARN: connection was reset during postJson')
|
2020-06-08 18:05:36 +00:00
|
|
|
return None
|
2020-06-23 21:39:19 +00:00
|
|
|
except ValueError as e:
|
|
|
|
print('ERROR: postJson failed ' + inboxUrl + ' ' +
|
|
|
|
json.dumps(postJsonObject) + ' ' + str(headers))
|
|
|
|
print(e)
|
|
|
|
return None
|
2019-10-26 12:01:22 +00:00
|
|
|
if postResult:
|
|
|
|
return postResult.text
|
|
|
|
return None
|
2019-07-16 14:23:06 +00:00
|
|
|
|
2020-04-04 11:00:19 +00:00
|
|
|
|
|
|
|
def postJsonString(session, postJsonStr: str,
|
|
|
|
federationList: [],
|
|
|
|
inboxUrl: str,
|
|
|
|
headers: {},
|
|
|
|
capability: str,
|
|
|
|
debug: bool) -> (bool, bool):
|
2019-08-17 10:15:01 +00:00
|
|
|
"""Post a json message string to the inbox of another person
|
|
|
|
Supplying a capability, such as "inbox:write"
|
2019-10-23 18:44:03 +00:00
|
|
|
The second boolean returned is true if the send is unauthorized
|
2019-08-17 10:15:01 +00:00
|
|
|
NOTE: Here we post a string rather than the original json so that
|
|
|
|
conversions between string and json format don't invalidate
|
|
|
|
the message body digest of http signatures
|
|
|
|
"""
|
|
|
|
# always allow capability requests
|
2020-03-22 21:16:02 +00:00
|
|
|
if not capability.startswith('cap'):
|
2019-08-17 10:15:01 +00:00
|
|
|
# check that we are posting to a permitted domain
|
2020-04-04 11:00:19 +00:00
|
|
|
if not urlPermitted(inboxUrl, federationList, capability):
|
|
|
|
print('postJson: ' + inboxUrl + ' not permitted by capabilities')
|
|
|
|
return None, None
|
|
|
|
|
2020-06-08 18:05:36 +00:00
|
|
|
try:
|
|
|
|
postResult = \
|
|
|
|
session.post(url=inboxUrl, data=postJsonStr, headers=headers)
|
2020-06-23 21:39:19 +00:00
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
print('WARN: error during postJsonString requests')
|
2020-06-23 13:41:12 +00:00
|
|
|
print(e)
|
|
|
|
return None, None
|
2020-06-23 13:28:41 +00:00
|
|
|
except SocketError as e:
|
|
|
|
if e.errno == errno.ECONNRESET:
|
|
|
|
print('WARN: connection was reset during postJsonString')
|
2020-06-08 18:05:36 +00:00
|
|
|
print('ERROR: postJsonString failed ' + inboxUrl + ' ' +
|
|
|
|
postJsonStr + ' ' + str(headers))
|
|
|
|
return None, None
|
2020-06-23 21:39:19 +00:00
|
|
|
except ValueError as e:
|
|
|
|
print('WARN: error during postJsonString')
|
|
|
|
print(e)
|
|
|
|
return None, None
|
2020-04-04 11:00:19 +00:00
|
|
|
if postResult.status_code < 200 or postResult.status_code > 202:
|
|
|
|
if postResult.status_code >= 400 and \
|
|
|
|
postResult.status_code <= 405 and \
|
|
|
|
postResult.status_code != 404:
|
|
|
|
print('WARN: >>> Post to ' + inboxUrl +
|
|
|
|
' is unauthorized. Code ' +
|
|
|
|
str(postResult.status_code) + ' <<<')
|
|
|
|
return False, True
|
2019-08-26 12:46:08 +00:00
|
|
|
else:
|
2020-04-04 11:00:19 +00:00
|
|
|
print('WARN: Failed to post to ' + inboxUrl +
|
|
|
|
' with headers ' + str(headers))
|
|
|
|
print('status code ' + str(postResult.status_code))
|
|
|
|
return False, False
|
|
|
|
return True, False
|
|
|
|
|
2019-08-17 10:15:01 +00:00
|
|
|
|
2020-04-04 11:00:19 +00:00
|
|
|
def postImage(session, attachImageFilename: str, federationList: [],
|
|
|
|
inboxUrl: str, headers: {}, capability: str) -> str:
|
2019-07-16 14:23:06 +00:00
|
|
|
"""Post an image to the inbox of another person or outbox via c2s
|
|
|
|
Supplying a capability, such as "inbox:write"
|
|
|
|
"""
|
|
|
|
# always allow capability requests
|
2020-03-22 21:16:02 +00:00
|
|
|
if not capability.startswith('cap'):
|
2019-07-16 14:23:06 +00:00
|
|
|
# check that we are posting to a permitted domain
|
2020-04-04 11:00:19 +00:00
|
|
|
if not urlPermitted(inboxUrl, federationList, capability):
|
|
|
|
print('postJson: ' + inboxUrl + ' not permitted')
|
2019-07-16 14:23:06 +00:00
|
|
|
return None
|
|
|
|
|
2020-04-04 11:00:19 +00:00
|
|
|
if not (attachImageFilename.endswith('.jpg') or
|
|
|
|
attachImageFilename.endswith('.jpeg') or
|
|
|
|
attachImageFilename.endswith('.png') or
|
2019-07-16 14:23:06 +00:00
|
|
|
attachImageFilename.endswith('.gif')):
|
|
|
|
print('Image must be png, jpg, or gif')
|
|
|
|
return None
|
|
|
|
if not os.path.isfile(attachImageFilename):
|
2020-04-04 11:00:19 +00:00
|
|
|
print('Image not found: ' + attachImageFilename)
|
2019-07-16 14:23:06 +00:00
|
|
|
return None
|
2020-04-04 11:00:19 +00:00
|
|
|
contentType = 'image/jpeg'
|
2019-07-16 14:23:06 +00:00
|
|
|
if attachImageFilename.endswith('.png'):
|
2020-04-04 11:00:19 +00:00
|
|
|
contentType = 'image/png'
|
2019-07-16 14:23:06 +00:00
|
|
|
if attachImageFilename.endswith('.gif'):
|
2020-04-04 11:00:19 +00:00
|
|
|
contentType = 'image/gif'
|
|
|
|
headers['Content-type'] = contentType
|
2019-07-16 14:23:06 +00:00
|
|
|
|
|
|
|
with open(attachImageFilename, 'rb') as avFile:
|
2020-04-04 11:00:19 +00:00
|
|
|
mediaBinary = avFile.read()
|
2020-06-08 18:05:36 +00:00
|
|
|
try:
|
|
|
|
postResult = session.post(url=inboxUrl, data=mediaBinary,
|
|
|
|
headers=headers)
|
2020-06-23 21:39:19 +00:00
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
print('WARN: error during postImage requests')
|
2020-06-23 13:41:12 +00:00
|
|
|
print(e)
|
|
|
|
return None
|
2020-06-23 13:28:41 +00:00
|
|
|
except SocketError as e:
|
|
|
|
if e.errno == errno.ECONNRESET:
|
|
|
|
print('WARN: connection was reset during postImage')
|
2020-06-08 18:05:36 +00:00
|
|
|
print('ERROR: postImage failed ' + inboxUrl + ' ' +
|
|
|
|
str(headers))
|
2020-06-23 13:41:12 +00:00
|
|
|
print(e)
|
2020-06-08 18:05:36 +00:00
|
|
|
return None
|
2020-06-23 21:39:19 +00:00
|
|
|
except ValueError as e:
|
|
|
|
print('WARN: error during postImage')
|
|
|
|
print(e)
|
|
|
|
return None
|
2019-10-26 12:01:22 +00:00
|
|
|
if postResult:
|
|
|
|
return postResult.text
|
2019-07-16 14:23:06 +00:00
|
|
|
return None
|