session.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. __filename__ = "session.py"
  2. __author__ = "Bob Mottram"
  3. __license__ = "AGPL3+"
  4. __version__ = "1.1.0"
  5. __maintainer__ = "Bob Mottram"
  6. __email__ = "bob@freedombone.net"
  7. __status__ = "Production"
  8. import os
  9. import requests
  10. from utils import urlPermitted
  11. import json
  12. from socket import error as SocketError
  13. import errno
  14. baseDirectory = None
  15. def createSession(proxyType: str):
  16. session = None
  17. try:
  18. session = requests.session()
  19. except requests.exceptions.RequestException as e:
  20. print('WARN: requests error during createSession')
  21. print(e)
  22. return None
  23. except SocketError as e:
  24. if e.errno == errno.ECONNRESET:
  25. print('WARN: connection was reset during createSession')
  26. else:
  27. print('WARN: socket error during createSession')
  28. print(e)
  29. return None
  30. except ValueError as e:
  31. print('WARN: error during createSession')
  32. print(e)
  33. return None
  34. if not session:
  35. return None
  36. if proxyType == 'tor':
  37. session.proxies = {}
  38. session.proxies['http'] = 'socks5h://localhost:9050'
  39. session.proxies['https'] = 'socks5h://localhost:9050'
  40. elif proxyType == 'i2p':
  41. session.proxies = {}
  42. session.proxies['http'] = 'socks5h://localhost:4447'
  43. session.proxies['https'] = 'socks5h://localhost:4447'
  44. elif proxyType == 'gnunet':
  45. session.proxies = {}
  46. session.proxies['http'] = 'socks5h://localhost:7777'
  47. session.proxies['https'] = 'socks5h://localhost:7777'
  48. # print('New session created with proxy ' + str(proxyType))
  49. return session
  50. def getJson(session, url: str, headers: {}, params: {},
  51. version='1.0.0', httpPrefix='https',
  52. domain='testdomain') -> {}:
  53. if not isinstance(url, str):
  54. print('url: ' + str(url))
  55. print('ERROR: getJson url should be a string')
  56. return None
  57. sessionParams = {}
  58. sessionHeaders = {}
  59. if headers:
  60. sessionHeaders = headers
  61. if params:
  62. sessionParams = params
  63. sessionHeaders['User-Agent'] = 'Epicyon/' + version
  64. if domain:
  65. sessionHeaders['User-Agent'] += \
  66. '; +' + httpPrefix + '://' + domain + '/'
  67. if not session:
  68. print('WARN: no session specified for getJson')
  69. try:
  70. result = session.get(url, headers=sessionHeaders, params=sessionParams)
  71. return result.json()
  72. except requests.exceptions.RequestException as e:
  73. print('ERROR: getJson failed\nurl: ' + str(url) + '\n' +
  74. 'headers: ' + str(sessionHeaders) + '\n' +
  75. 'params: ' + str(sessionParams) + '\n')
  76. print(e)
  77. except ValueError as e:
  78. print('ERROR: getJson failed\nurl: ' + str(url) + '\n' +
  79. 'headers: ' + str(sessionHeaders) + '\n' +
  80. 'params: ' + str(sessionParams) + '\n')
  81. print(e)
  82. except SocketError as e:
  83. if e.errno == errno.ECONNRESET:
  84. print('WARN: connection was reset during getJson')
  85. print(e)
  86. return None
  87. def postJson(session, postJsonObject: {}, federationList: [],
  88. inboxUrl: str, headers: {}, capability: str) -> str:
  89. """Post a json message to the inbox of another person
  90. Supplying a capability, such as "inbox:write"
  91. """
  92. # always allow capability requests
  93. if not capability.startswith('cap'):
  94. # check that we are posting to a permitted domain
  95. if not urlPermitted(inboxUrl, federationList, capability):
  96. print('postJson: ' + inboxUrl + ' not permitted')
  97. return None
  98. try:
  99. postResult = \
  100. session.post(url=inboxUrl,
  101. data=json.dumps(postJsonObject),
  102. headers=headers)
  103. except requests.exceptions.RequestException as e:
  104. print('ERROR: postJson requests failed ' + inboxUrl + ' ' +
  105. json.dumps(postJsonObject) + ' ' + str(headers))
  106. print(e)
  107. return None
  108. except SocketError as e:
  109. if e.errno == errno.ECONNRESET:
  110. print('WARN: connection was reset during postJson')
  111. return None
  112. except ValueError as e:
  113. print('ERROR: postJson failed ' + inboxUrl + ' ' +
  114. json.dumps(postJsonObject) + ' ' + str(headers))
  115. print(e)
  116. return None
  117. if postResult:
  118. return postResult.text
  119. return None
  120. def postJsonString(session, postJsonStr: str,
  121. federationList: [],
  122. inboxUrl: str,
  123. headers: {},
  124. capability: str,
  125. debug: bool) -> (bool, bool):
  126. """Post a json message string to the inbox of another person
  127. Supplying a capability, such as "inbox:write"
  128. The second boolean returned is true if the send is unauthorized
  129. NOTE: Here we post a string rather than the original json so that
  130. conversions between string and json format don't invalidate
  131. the message body digest of http signatures
  132. """
  133. # always allow capability requests
  134. if not capability.startswith('cap'):
  135. # check that we are posting to a permitted domain
  136. if not urlPermitted(inboxUrl, federationList, capability):
  137. print('postJson: ' + inboxUrl + ' not permitted by capabilities')
  138. return None, None
  139. try:
  140. postResult = \
  141. session.post(url=inboxUrl, data=postJsonStr, headers=headers)
  142. except requests.exceptions.RequestException as e:
  143. print('WARN: error during postJsonString requests')
  144. print(e)
  145. return None, None
  146. except SocketError as e:
  147. if e.errno == errno.ECONNRESET:
  148. print('WARN: connection was reset during postJsonString')
  149. print('ERROR: postJsonString failed ' + inboxUrl + ' ' +
  150. postJsonStr + ' ' + str(headers))
  151. return None, None
  152. except ValueError as e:
  153. print('WARN: error during postJsonString')
  154. print(e)
  155. return None, None
  156. if postResult.status_code < 200 or postResult.status_code > 202:
  157. if postResult.status_code >= 400 and \
  158. postResult.status_code <= 405 and \
  159. postResult.status_code != 404:
  160. print('WARN: Post to ' + inboxUrl + ' is unauthorized. Code ' +
  161. str(postResult.status_code))
  162. return False, True
  163. else:
  164. print('WARN: Failed to post to ' + inboxUrl +
  165. ' with headers ' + str(headers))
  166. print('status code ' + str(postResult.status_code))
  167. return False, False
  168. return True, False
  169. def postImage(session, attachImageFilename: str, federationList: [],
  170. inboxUrl: str, headers: {}, capability: str) -> str:
  171. """Post an image to the inbox of another person or outbox via c2s
  172. Supplying a capability, such as "inbox:write"
  173. """
  174. # always allow capability requests
  175. if not capability.startswith('cap'):
  176. # check that we are posting to a permitted domain
  177. if not urlPermitted(inboxUrl, federationList, capability):
  178. print('postJson: ' + inboxUrl + ' not permitted')
  179. return None
  180. if not (attachImageFilename.endswith('.jpg') or
  181. attachImageFilename.endswith('.jpeg') or
  182. attachImageFilename.endswith('.png') or
  183. attachImageFilename.endswith('.gif')):
  184. print('Image must be png, jpg, or gif')
  185. return None
  186. if not os.path.isfile(attachImageFilename):
  187. print('Image not found: ' + attachImageFilename)
  188. return None
  189. contentType = 'image/jpeg'
  190. if attachImageFilename.endswith('.png'):
  191. contentType = 'image/png'
  192. if attachImageFilename.endswith('.gif'):
  193. contentType = 'image/gif'
  194. headers['Content-type'] = contentType
  195. with open(attachImageFilename, 'rb') as avFile:
  196. mediaBinary = avFile.read()
  197. try:
  198. postResult = session.post(url=inboxUrl, data=mediaBinary,
  199. headers=headers)
  200. except requests.exceptions.RequestException as e:
  201. print('WARN: error during postImage requests')
  202. print(e)
  203. return None
  204. except SocketError as e:
  205. if e.errno == errno.ECONNRESET:
  206. print('WARN: connection was reset during postImage')
  207. print('ERROR: postImage failed ' + inboxUrl + ' ' +
  208. str(headers))
  209. print(e)
  210. return None
  211. except ValueError as e:
  212. print('WARN: error during postImage')
  213. print(e)
  214. return None
  215. if postResult:
  216. return postResult.text
  217. return None