2020-03-31 06:48:20 +00:00
|
|
|
'''Onionr - Private P2P Communication.
|
2019-06-26 20:13:36 +00:00
|
|
|
|
|
|
|
Do HTTP GET or POST requests through a proxy
|
|
|
|
'''
|
2020-03-31 06:48:20 +00:00
|
|
|
from ipaddress import IPv4Address
|
|
|
|
from urllib.parse import urlparse
|
|
|
|
|
|
|
|
import requests, streamedrequests
|
|
|
|
import logger, onionrexceptions
|
|
|
|
from etc import onionrvalues
|
|
|
|
from . import localcommand
|
2019-06-26 20:13:36 +00:00
|
|
|
'''
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
'''
|
2020-03-31 06:48:20 +00:00
|
|
|
|
|
|
|
|
2019-09-12 15:54:36 +00:00
|
|
|
def do_post_request(url, data={}, port=0, proxyType='tor', max_size=10000, content_type: str = ''):
|
2020-03-31 06:48:20 +00:00
|
|
|
'''Do a POST request through a local tor or i2p instance.'''
|
2019-06-23 07:25:40 +00:00
|
|
|
if proxyType == 'tor':
|
|
|
|
if port == 0:
|
2019-08-04 04:52:57 +00:00
|
|
|
port = localcommand.local_command('/gettorsocks')
|
2019-06-23 07:25:40 +00:00
|
|
|
proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)}
|
|
|
|
elif proxyType == 'i2p':
|
|
|
|
proxies = {'http': 'http://127.0.0.1:4444'}
|
2020-03-31 06:48:20 +00:00
|
|
|
elif proxyType == 'lan':
|
|
|
|
address = urlparse(url).hostname
|
|
|
|
if IPv4Address(address).is_private and not IPv4Address(address).is_loopback:
|
|
|
|
proxies = {}
|
|
|
|
else:
|
|
|
|
return
|
2019-06-23 07:25:40 +00:00
|
|
|
else:
|
|
|
|
return
|
2019-08-28 23:33:28 +00:00
|
|
|
headers = {'User-Agent': 'PyOnionr', 'Connection':'close'}
|
2019-09-12 15:54:36 +00:00
|
|
|
if len(content_type) > 0:
|
|
|
|
headers['Content-Type'] = content_type
|
2019-06-23 07:25:40 +00:00
|
|
|
try:
|
|
|
|
proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)}
|
2019-07-10 07:29:05 +00:00
|
|
|
#r = requests.post(url, data=data, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30))
|
|
|
|
r = streamedrequests.post(url, post_data=data, request_headers=headers, proxy=proxies, connect_timeout=15, stream_timeout=30, max_size=max_size, allow_redirects=False)
|
|
|
|
retData = r[1]
|
2019-06-23 07:25:40 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
raise KeyboardInterrupt
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
logger.debug('Error: %s' % str(e))
|
|
|
|
retData = False
|
|
|
|
return retData
|
|
|
|
|
2020-03-31 06:48:20 +00:00
|
|
|
|
2019-07-22 02:23:22 +00:00
|
|
|
def do_get_request(url, port=0, proxyType='tor', ignoreAPI=False, returnHeaders=False, max_size=5242880):
|
2019-06-23 07:25:40 +00:00
|
|
|
'''
|
|
|
|
Do a get request through a local tor or i2p instance
|
|
|
|
'''
|
2019-07-30 05:19:22 +00:00
|
|
|
API_VERSION = onionrvalues.API_VERSION
|
2019-06-23 07:25:40 +00:00
|
|
|
retData = False
|
|
|
|
if proxyType == 'tor':
|
|
|
|
if port == 0:
|
2020-03-31 06:48:20 +00:00
|
|
|
port = localcommand.local_command('/gettorsocks')
|
2019-06-23 07:25:40 +00:00
|
|
|
proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)}
|
|
|
|
elif proxyType == 'i2p':
|
|
|
|
proxies = {'http': 'http://127.0.0.1:4444'}
|
2020-03-31 06:48:20 +00:00
|
|
|
elif proxyType == 'lan':
|
|
|
|
address = urlparse(url).hostname
|
|
|
|
if IPv4Address(address).is_private and not IPv4Address(address).is_loopback:
|
|
|
|
proxies = {}
|
|
|
|
else:
|
|
|
|
return
|
2019-06-23 07:25:40 +00:00
|
|
|
else:
|
|
|
|
return
|
2019-08-28 23:33:28 +00:00
|
|
|
headers = {'User-Agent': 'PyOnionr', 'Connection':'close'}
|
2019-06-23 07:25:40 +00:00
|
|
|
response_headers = dict()
|
|
|
|
try:
|
|
|
|
proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)}
|
2019-07-10 07:29:05 +00:00
|
|
|
r = streamedrequests.get(url, request_headers=headers, allow_redirects=False, proxy=proxies, connect_timeout=15, stream_timeout=120, max_size=max_size)
|
2019-06-23 07:25:40 +00:00
|
|
|
# Check server is using same API version as us
|
|
|
|
if not ignoreAPI:
|
|
|
|
try:
|
2019-07-09 06:25:20 +00:00
|
|
|
response_headers = r[0].headers
|
|
|
|
if r[0].headers['X-API'] != str(API_VERSION):
|
2019-06-23 07:25:40 +00:00
|
|
|
raise onionrexceptions.InvalidAPIVersion
|
|
|
|
except KeyError:
|
|
|
|
raise onionrexceptions.InvalidAPIVersion
|
2019-07-09 06:25:20 +00:00
|
|
|
retData = r[1]
|
2019-06-23 07:25:40 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
raise KeyboardInterrupt
|
|
|
|
except ValueError as e:
|
|
|
|
pass
|
|
|
|
except onionrexceptions.InvalidAPIVersion:
|
|
|
|
if 'X-API' in response_headers:
|
|
|
|
logger.debug('Using API version %s. Cannot communicate with node\'s API version of %s.' % (API_VERSION, response_headers['X-API']))
|
|
|
|
else:
|
|
|
|
logger.debug('Using API version %s. API version was not sent with the request.' % API_VERSION)
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
if not 'ConnectTimeoutError' in str(e) and not 'Request rejected or failed' in str(e):
|
|
|
|
logger.debug('Error: %s' % str(e))
|
|
|
|
retData = False
|
|
|
|
if returnHeaders:
|
|
|
|
return (retData, response_headers)
|
|
|
|
else:
|
2019-08-09 20:41:27 +00:00
|
|
|
return retData
|