Begin support for ipfs

main
Bob Mottram 2022-04-29 14:54:13 +01:00
parent f1d9f75095
commit 05efb23a51
17 changed files with 135 additions and 34 deletions

View File

@ -234,7 +234,9 @@ def dangerous_css(filename: str, allow_local_network_access: bool) -> bool:
if ctr > 0:
if ')' in url_str:
url_str = url_str.split(')')[0]
if 'http' in url_str:
if 'http' in url_str or \
'ipfs' in url_str or \
'ipns' in url_str:
print('ERROR: non-local web link in CSS ' +
filename)
return True
@ -1114,6 +1116,8 @@ def get_mentions_from_html(html_text: str, match_str: str) -> []:
if actor_str.startswith('http') or \
actor_str.startswith('gnunet') or \
actor_str.startswith('i2p') or \
actor_str.startswith('ipfs') or \
actor_str.startswith('ipns') or \
actor_str.startswith('hyper') or \
actor_str.startswith('dat:'):
if actor_str not in mentions:

View File

@ -2219,7 +2219,9 @@ class PubServer(BaseHTTPRequestHandler):
else:
search_handle = ''
if '@' not in search_handle:
if search_handle.startswith('http'):
if search_handle.startswith('http') or \
search_handle.startswith('ipfs') or \
search_handle.startswith('ipns'):
search_nickname = \
get_nickname_from_actor(search_handle)
if search_nickname:
@ -2286,6 +2288,8 @@ class PubServer(BaseHTTPRequestHandler):
print('moderation_text: ' + moderation_text)
nickname = moderation_text
if nickname.startswith('http') or \
nickname.startswith('ipfs') or \
nickname.startswith('ipns') or \
nickname.startswith('hyper'):
nickname = get_nickname_from_actor(nickname)
if '@' in nickname:
@ -2301,6 +2305,8 @@ class PubServer(BaseHTTPRequestHandler):
if moderation_button == 'block':
full_block_domain = None
if moderation_text.startswith('http') or \
moderation_text.startswith('ipfs') or \
moderation_text.startswith('ipns') or \
moderation_text.startswith('hyper'):
# https://domain
block_domain, block_port = \
@ -2320,6 +2326,8 @@ class PubServer(BaseHTTPRequestHandler):
if moderation_button == 'unblock':
full_block_domain = None
if moderation_text.startswith('http') or \
moderation_text.startswith('ipfs') or \
moderation_text.startswith('ipns') or \
moderation_text.startswith('hyper'):
# https://domain
block_domain, block_port = \

View File

@ -882,9 +882,12 @@ def _desktop_show_profile(session, nickname: str, domain: str,
is_http = False
if 'http://' in actor:
is_http = True
is_gnunet = False
is_ipfs = False
is_ipns = False
actor_json, _ = \
get_actor_json(domain, actor, is_http, False, False, True,
signing_priv_key_pem, session)
get_actor_json(domain, actor, is_http, is_gnunet, is_ipfs, is_ipns,
False, True, signing_priv_key_pem, session)
_desktop_show_actor(base_dir, actor_json, translate,
system_language, screenreader, espeak)
@ -904,7 +907,8 @@ def _desktop_show_profile_from_handle(session, nickname: str, domain: str,
Returns the actor json
"""
actor_json, _ = \
get_actor_json(domain, handle, False, False, False, True,
get_actor_json(domain, handle, False, False, False, False,
False, True,
signing_priv_key_pem, session)
_desktop_show_actor(base_dir, actor_json, translate,

View File

@ -503,6 +503,12 @@ parser.add_argument("--http", type=str2bool, nargs='?',
parser.add_argument("--gnunet", type=str2bool, nargs='?',
const=True, default=False,
help="Use gnunet protocol only")
parser.add_argument("--ipfs", type=str2bool, nargs='?',
const=True, default=False,
help="Use ipfs protocol only")
parser.add_argument("--ipns", type=str2bool, nargs='?',
const=True, default=False,
help="Use ipns protocol only")
parser.add_argument("--dat", type=str2bool, nargs='?',
const=True, default=False,
help="Use dat protocol only")
@ -736,6 +742,10 @@ if args.testsnetwork:
http_prefix = 'https'
if args.http or args.i2p:
http_prefix = 'http'
elif args.ipfs:
http_prefix = 'ipfs'
elif args.ipns:
http_prefix = 'ipns'
elif args.gnunet:
http_prefix = 'gnunet'
@ -2282,6 +2292,10 @@ if args.gnunet:
http_prefix = 'gnunet'
if args.dat or args.hyper:
http_prefix = 'hyper'
if args.ipfs:
http_prefix = 'ipfs'
if args.ipns:
http_prefix = 'ipns'
if args.i2p:
http_prefix = 'http'
@ -2295,6 +2309,14 @@ if args.migrations:
http_prefix = 'http'
port = 80
proxy_type = 'i2p'
elif args.ipfs:
http_prefix = 'ipfs'
port = 80
proxy_type = 'ipfs'
elif args.ipns:
http_prefix = 'ipns'
port = 80
proxy_type = 'ipfs'
elif args.gnunet:
http_prefix = 'gnunet'
port = 80
@ -2328,6 +2350,7 @@ if args.actor:
else:
print('Did not obtain instance actor key for ' + domain)
get_actor_json(domain, args.actor, args.http, args.gnunet,
args.ipfs, args.ipns,
debug, False, signing_priv_key_pem, None)
sys.exit()
@ -2336,6 +2359,8 @@ if args.followers:
if '/@' in args.followers or \
'/users/' in args.followers or \
args.followers.startswith('http') or \
args.followers.startswith('ipfs') or \
args.followers.startswith('ipns') or \
args.followers.startswith('hyper'):
# format: https://domain/@nick
prefixes = get_protocol_prefixes()
@ -2400,6 +2425,14 @@ if args.followers:
http_prefix = 'gnunet'
port = 80
proxy_type = 'gnunet'
elif args.ipfs:
http_prefix = 'ipfs'
port = 80
proxy_type = 'ipfs'
elif args.ipns:
http_prefix = 'ipns'
port = 80
proxy_type = 'ipfs'
else:
http_prefix = 'https'
port = 443
@ -2512,6 +2545,12 @@ if args.addaccount:
domain.endswith('.i2p'):
port = 80
http_prefix = 'http'
if domain.endswith('.ipfs'):
port = 80
http_prefix = 'ipfs'
if domain.endswith('.ipns'):
port = 80
http_prefix = 'ipns'
create_person(base_dir, nickname, domain, port, http_prefix,
True, not args.noapproval, args.password.strip())
if os.path.isdir(account_dir):

View File

@ -414,6 +414,8 @@ def _get_no_of_follows(base_dir: str, nickname: str, domain: str,
not line.startswith('http'):
ctr += 1
elif ((line.startswith('http') or
line.startswith('ipfs') or
line.startswith('ipns') or
line.startswith('hyper')) and
has_users_path(line)):
ctr += 1
@ -542,6 +544,8 @@ def get_following_feed(base_dir: str, domain: str, port: int, path: str,
url = http_prefix + '://' + dom + '/c/' + nick
following['orderedItems'].append(url)
elif ((line.startswith('http') or
line.startswith('ipfs') or
line.startswith('ipns') or
line.startswith('hyper')) and
has_users_path(line)):
# https://domain/users/nickname

View File

@ -87,8 +87,15 @@ def _update_moved_handle(base_dir: str, nickname: str, domain: str,
gnunet = False
if http_prefix == 'gnunet':
gnunet = True
ipfs = False
if http_prefix == 'ipfs':
ipfs = True
ipns = False
if http_prefix == 'ipns':
ipns = True
person_json = \
get_actor_json(domain, person_url, http_prefix, gnunet, debug, False,
get_actor_json(domain, person_url, http_prefix, gnunet, ipfs, ipns,
debug, False,
signing_priv_key_pem, None)
if not person_json:
return ctr

View File

@ -471,7 +471,7 @@ def _valid_podcast_entry(base_dir: str, key: str, entry: {}) -> bool:
https://github.com/Podcastindex-org/podcast-namespace/
blob/main/proposal-docs/social/social.md#socialinteract-element
"""
if key == 'socialInteract':
if key == 'socialInteract' or key == 'discussion':
if not entry.get('protocol'):
return False
if not entry.get('uri'):
@ -515,7 +515,9 @@ def xml_podcast_to_dict(base_dir: str, xml_item: str, xml_str: str) -> {}:
"transcripts": [],
"valueRecipients": [],
"trailers": [],
"socialInteract": []
"discussion": [],
"episode": '',
"socialInteract": [],
}
pod_lines = xml_item.split('<podcast:')
@ -529,7 +531,8 @@ def xml_podcast_to_dict(base_dir: str, xml_item: str, xml_str: str) -> {}:
pod_val = pod_line.split('>', 1)[1].strip()
if '<' in pod_val:
pod_val = pod_val.split('<')[0]
podcast_properties[pod_key] = pod_val
if pod_key in podcast_properties:
podcast_properties[pod_key] = pod_val
ctr += 1
continue
pod_key = pod_line.split(' ')[0]

View File

@ -1478,6 +1478,7 @@ def _detect_users_path(url: str) -> str:
def get_actor_json(host_domain: str, handle: str, http: bool, gnunet: bool,
ipfs: bool, ipns: bool,
debug: bool, quiet: bool,
signing_priv_key_pem: str,
existing_session) -> ({}, {}):
@ -1493,6 +1494,8 @@ def get_actor_json(host_domain: str, handle: str, http: bool, gnunet: bool,
if '/@' in handle or \
detected_users_path in handle or \
handle.startswith('http') or \
handle.startswith('ipfs') or \
handle.startswith('ipns') or \
handle.startswith('hyper'):
group_paths = get_group_paths()
if detected_users_path in group_paths:
@ -1558,6 +1561,12 @@ def get_actor_json(host_domain: str, handle: str, http: bool, gnunet: bool,
elif gnunet:
http_prefix = 'gnunet'
proxy_type = 'gnunet'
elif ipfs:
http_prefix = 'ipfs'
proxy_type = 'ipfs'
elif ipns:
http_prefix = 'ipns'
proxy_type = 'ipfs'
else:
if '127.0.' not in domain and '192.168.' not in domain:
http_prefix = 'https'
@ -1741,8 +1750,12 @@ def valid_sending_actor(session, base_dir: str,
# NOTE: the actor should not be obtained from the local cache,
# because they may have changed fields which are being tested here,
# such as the bio length
gnunet = False
ipfs = False
ipns = False
actor_json, _ = get_actor_json(domain, sending_actor,
True, False, debug, True,
True, gnunet, ipfs, ipns,
debug, True,
signing_priv_key_pem, session)
if not actor_json:
# if the actor couldn't be obtained then proceed anyway

8
pgp.py
View File

@ -439,8 +439,8 @@ def _get_pgp_public_key_from_actor(signing_priv_key_pem: str,
"""
if not actor_json:
actor_json, _ = \
get_actor_json(domain, handle, False, False, False, True,
signing_priv_key_pem, None)
get_actor_json(domain, handle, False, False, False, False,
False, True, signing_priv_key_pem, None)
if not actor_json:
return None
if not actor_json.get('attachment'):
@ -498,8 +498,8 @@ def pgp_public_key_upload(base_dir: str, session,
print('Getting actor for ' + handle)
actor_json, _ = \
get_actor_json(domain_full, handle, False, False, debug, True,
signing_priv_key_pem, session)
get_actor_json(domain_full, handle, False, False, False, False,
debug, True, signing_priv_key_pem, session)
if not actor_json:
if debug:
print('No actor returned for ' + handle)

View File

@ -2196,7 +2196,10 @@ def create_report_post(base_dir: str,
if moderator_actor not in moderators_list:
moderators_list.append(moderator_actor)
continue
if line.startswith('http') or line.startswith('hyper'):
if line.startswith('http') or \
line.startswith('ipfs') or \
line.startswith('ipns') or \
line.startswith('hyper'):
# must be a local address - no remote moderators
if '://' + domain_full + '/' in line:
if line not in moderators_list:

View File

@ -374,7 +374,7 @@ def load_document(url):
# validate URL
pieces = urllib_parse.urlparse(url)
if (not all([pieces.scheme, pieces.netloc]) or
pieces.scheme not in ['http', 'https', 'hyper'] or
pieces.scheme not in ['http', 'https', 'hyper', 'ipfs', 'ipns'] or
set(pieces.netloc) > set(
string.ascii_letters + string.digits + '-.:')):
raise JsonLdError(

View File

@ -49,6 +49,9 @@ def create_session(proxy_type: str):
session.proxies = {}
session.proxies['http'] = 'socks5h://localhost:7777'
session.proxies['https'] = 'socks5h://localhost:7777'
elif proxy_type == 'ipfs' or proxy_type == 'ipns':
session.proxies = {}
session.proxies['ipfs'] = 'socks5h://localhost:4001'
# print('New session created with proxy ' + str(proxy_type))
return session

View File

@ -66,7 +66,7 @@ def _site_active_parse_url(url):
return loc
def _site_a_ctive_http_connect(loc, timeout: int):
def _site_active_http_connect(loc, timeout: int):
"""Connects to the host and returns an HTTP or HTTPS connections."""
if loc.scheme == "https":
ssl_context = ssl.SSLContext()
@ -78,7 +78,7 @@ def _site_a_ctive_http_connect(loc, timeout: int):
def _site_active_http_request(loc, timeout: int):
"""Performs a HTTP request and return response in a Result object.
"""
conn = _site_a_ctive_http_connect(loc, timeout)
conn = _site_active_http_connect(loc, timeout)
method = 'HEAD'
conn.request(method, loc.path)
@ -98,7 +98,9 @@ def site_is_active(url: str, timeout: int) -> bool:
This can be used to check that an instance is online before
trying to send posts to it.
"""
if not url.startswith('http'):
if not url.startswith('http') and \
not url.startswith('ipfs') and \
not url.startswith('ipns'):
return False
if '.onion/' in url or '.i2p/' in url or \
url.endswith('.onion') or \

View File

@ -6779,7 +6779,7 @@ def _test_xml_podcast_dict(base_dir: str) -> None:
'</rss>'
podcast_properties = xml_podcast_to_dict(base_dir, xml_str, xml_str)
assert podcast_properties
# pprint(podcast_properties)
pprint(podcast_properties)
assert podcast_properties.get('valueRecipients')
assert podcast_properties.get('persons')
assert podcast_properties.get('soundbites')

View File

@ -654,6 +654,7 @@ def get_protocol_prefixes() -> []:
"""
return ('https://', 'http://', 'ftp://',
'dat://', 'i2p://', 'gnunet://',
'ipfs://', 'ipns://',
'hyper://', 'gemini://', 'gopher://')
@ -1963,7 +1964,7 @@ def _get_reserved_words() -> str:
'ignores', 'linksmobile', 'newswiremobile',
'minimal', 'search', 'eventdelete',
'searchemoji', 'catalog', 'conversationId',
'mention', 'http', 'https',
'mention', 'http', 'https', 'ipfs', 'ipns',
'ontologies', 'data')

View File

@ -28,23 +28,26 @@ def _html_podcast_social_interactions(podcast_properties: {},
"""
if not podcast_properties:
return ''
if not podcast_properties.get('socialInteract'):
return ''
if podcast_properties['socialInteract'].get('uri'):
episode_post_url = podcast_properties['socialInteract']['uri']
elif podcast_properties['socialInteract'].get('url'):
episode_post_url = podcast_properties['socialInteract']['url']
elif podcast_properties['socialInteract'].get('text'):
episode_post_url = podcast_properties['socialInteract']['text']
key = 'discussion'
if not podcast_properties.get(key):
key = 'socialInteract'
if not podcast_properties.get(key):
return ''
if podcast_properties[key].get('uri'):
episode_post_url = podcast_properties[key]['uri']
elif podcast_properties[key].get('url'):
episode_post_url = podcast_properties[key]['url']
elif podcast_properties[key].get('text'):
episode_post_url = podcast_properties[key]['text']
else:
return ''
actor_str = ''
podcast_account_id = None
if podcast_properties['socialInteract'].get('accountId'):
podcast_account_id = podcast_properties['socialInteract']['accountId']
elif podcast_properties['socialInteract'].get('podcastAccountUrl'):
if podcast_properties[key].get('accountId'):
podcast_account_id = podcast_properties[key]['accountId']
elif podcast_properties[key].get('podcastAccountUrl'):
podcast_account_id = \
podcast_properties['socialInteract']['podcastAccountUrl']
podcast_properties[key]['podcastAccountUrl']
if podcast_account_id:
actor_handle = podcast_account_id
if actor_handle.startswith('@'):

View File

@ -152,10 +152,16 @@ def html_profile_after_search(css_cache: {},
"""
http = False
gnunet = False
ipfs = False
ipns = False
if http_prefix == 'http':
http = True
elif http_prefix == 'gnunet':
gnunet = True
elif http_prefix == 'ipfs':
ipfs = True
elif http_prefix == 'ipns':
ipns = True
from_domain = domain
if onion_domain:
if '.onion/' in profile_handle or profile_handle.endswith('.onion'):
@ -166,7 +172,8 @@ def html_profile_after_search(css_cache: {},
from_domain = i2p_domain
http = True
profile_json, as_header = \
get_actor_json(from_domain, profile_handle, http, gnunet, debug, False,
get_actor_json(from_domain, profile_handle, http,
gnunet, ipfs, ipns, debug, False,
signing_priv_key_pem, session)
if not profile_json:
return None