merge-requests/30/head
Bob Mottram 2023-01-17 13:32:03 +00:00
commit a64b0d2bf4
19 changed files with 387 additions and 191 deletions

View File

@ -91,6 +91,9 @@ def outbox_announce(recent_posts_cache: {},
print('WARN: no nickname found in ' + message_json['actor']) print('WARN: no nickname found in ' + message_json['actor'])
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(message_json['actor'])
if not domain:
print('WARN: no domain found in ' + message_json['actor'])
return False
post_filename = locate_post(base_dir, nickname, domain, post_filename = locate_post(base_dir, nickname, domain,
message_json['object']) message_json['object'])
if post_filename: if post_filename:
@ -110,6 +113,9 @@ def outbox_announce(recent_posts_cache: {},
print('WARN: no nickname found in ' + message_json['actor']) print('WARN: no nickname found in ' + message_json['actor'])
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(message_json['actor'])
if not domain:
print('WARN: no domain found in ' + message_json['actor'])
return False
post_filename = locate_post(base_dir, nickname, domain, post_filename = locate_post(base_dir, nickname, domain,
message_json['object']['object']) message_json['object']['object'])
if post_filename: if post_filename:
@ -187,8 +193,8 @@ def create_announce(session, base_dir: str, federation_list: [],
group_account = False group_account = False
if has_users_path(object_url): if has_users_path(object_url):
announce_nickname = get_nickname_from_actor(object_url) announce_nickname = get_nickname_from_actor(object_url)
if announce_nickname: announce_domain, announce_port = get_domain_from_actor(object_url)
announce_domain, announce_port = get_domain_from_actor(object_url) if announce_nickname and announce_domain:
if '/' + str(announce_nickname) + '/' in object_url: if '/' + str(announce_nickname) + '/' in object_url:
announce_actor = \ announce_actor = \
object_url.split('/' + announce_nickname + '/')[0] + \ object_url.split('/' + announce_nickname + '/')[0] + \

View File

@ -73,6 +73,8 @@ def outbox_availability(base_dir: str, nickname: str, message_json: {},
if actor_nickname != nickname: if actor_nickname != nickname:
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(message_json['actor'])
if not domain:
return False
status = message_json['object'].replace('"', '') status = message_json['object'].replace('"', '')
return set_availability(base_dir, nickname, domain, status) return set_availability(base_dir, nickname, domain, status)

View File

@ -814,6 +814,9 @@ def outbox_block(base_dir: str, nickname: str, domain: str,
return False return False
domain_blocked, port_blocked = \ domain_blocked, port_blocked = \
get_domain_from_actor(message_json['object']) get_domain_from_actor(message_json['object'])
if not domain_blocked:
print('WARN: unable to find domain in ' + message_json['object'])
return False
domain_blocked_full = get_full_domain(domain_blocked, port_blocked) domain_blocked_full = get_full_domain(domain_blocked, port_blocked)
add_block(base_dir, nickname, domain, add_block(base_dir, nickname, domain,
@ -872,6 +875,10 @@ def outbox_undo_block(base_dir: str, nickname: str, domain: str,
return return
domain_object = message_json['object']['object'] domain_object = message_json['object']['object']
domain_blocked, port_blocked = get_domain_from_actor(domain_object) domain_blocked, port_blocked = get_domain_from_actor(domain_object)
if not domain_blocked:
print('WARN: unable to find domain in ' +
message_json['object']['object'])
return
domain_blocked_full = get_full_domain(domain_blocked, port_blocked) domain_blocked_full = get_full_domain(domain_blocked, port_blocked)
remove_block(base_dir, nickname, domain, remove_block(base_dir, nickname, domain,

174
daemon.py
View File

@ -679,29 +679,34 @@ class PubServer(BaseHTTPRequestHandler):
self.server.person_cache) self.server.person_cache)
reply_to_nickname = get_nickname_from_actor(in_reply_to) reply_to_nickname = get_nickname_from_actor(in_reply_to)
reply_to_domain, reply_to_port = get_domain_from_actor(in_reply_to) reply_to_domain, reply_to_port = get_domain_from_actor(in_reply_to)
reply_to_domain_full = get_full_domain(reply_to_domain, reply_to_port) message_json = None
mentions_str = '@' + reply_to_nickname + '@' + reply_to_domain_full if reply_to_nickname and reply_to_domain:
reply_to_domain_full = \
get_full_domain(reply_to_domain, reply_to_port)
mentions_str = '@' + reply_to_nickname + '@' + reply_to_domain_full
message_json = \ message_json = \
create_direct_message_post(self.server.base_dir, nickname, create_direct_message_post(self.server.base_dir, nickname,
self.server.domain, self.server.port, self.server.domain,
self.server.http_prefix, self.server.port,
mentions_str + ' ' + answer, self.server.http_prefix,
False, False, mentions_str + ' ' + answer,
comments_enabled, False, False,
attach_image_filename, comments_enabled,
media_type, image_description, city, attach_image_filename,
in_reply_to, in_reply_to_atom_uri, media_type, image_description, city,
subject, self.server.debug, in_reply_to, in_reply_to_atom_uri,
schedule_post, subject, self.server.debug,
event_date, event_time, schedule_post,
event_end_time, event_date, event_time,
location, self.server.system_language, event_end_time,
conversation_id, location,
self.server.low_bandwidth, self.server.system_language,
self.server.content_license_url, conversation_id,
languages_understood, False, self.server.low_bandwidth,
self.server.translate, buy_url) self.server.content_license_url,
languages_understood, False,
self.server.translate, buy_url)
if message_json: if message_json:
# NOTE: content and contentMap are not required, but we will keep # NOTE: content and contentMap are not required, but we will keep
# them in there so that the post does not get filtered out by # them in there so that the post does not get filtered out by
@ -2082,6 +2087,8 @@ class PubServer(BaseHTTPRequestHandler):
for to_actor in message_json['object']['to']: for to_actor in message_json['object']['to']:
to_domain, to_port = \ to_domain, to_port = \
get_domain_from_actor(to_actor) get_domain_from_actor(to_actor)
if not to_domain:
continue
to_domain_full = \ to_domain_full = \
get_full_domain(to_domain, to_port) get_full_domain(to_domain, to_port)
if self.server.domain_full != to_domain_full: if self.server.domain_full != to_domain_full:
@ -2095,14 +2102,16 @@ class PubServer(BaseHTTPRequestHandler):
local_actor = message_json['object']['attributedTo'] local_actor = message_json['object']['attributedTo']
local_domain, local_port = \ local_domain, local_port = \
get_domain_from_actor(local_actor) get_domain_from_actor(local_actor)
local_domain_full = \ if local_domain:
get_full_domain(local_domain, local_port) local_domain_full = \
if self.server.domain_full != local_domain_full: get_full_domain(local_domain, local_port)
print("REJECT: inbox local only post isn't local " + if self.server.domain_full != local_domain_full:
str(message_json)) print("REJECT: " +
self._400() "inbox local only post isn't local " +
self.server.postreq_busy = False str(message_json))
return 3 self._400()
self.server.postreq_busy = False
return 3
# actor should look like a url # actor should look like a url
if debug: if debug:
@ -2130,6 +2139,11 @@ class PubServer(BaseHTTPRequestHandler):
message_domain, _ = \ message_domain, _ = \
get_domain_from_actor(message_json['actor']) get_domain_from_actor(message_json['actor'])
if not message_domain:
print('INBOX: POST from unknown domain ' + message_json['actor'])
self._400()
self.server.postreq_busy = False
return 3
self.server.blocked_cache_last_updated = \ self.server.blocked_cache_last_updated = \
update_blocked_cache(self.server.base_dir, update_blocked_cache(self.server.base_dir,
@ -2609,8 +2623,11 @@ class PubServer(BaseHTTPRequestHandler):
if search_nickname: if search_nickname:
search_domain, _ = \ search_domain, _ = \
get_domain_from_actor(search_handle) get_domain_from_actor(search_handle)
search_handle = \ if search_domain:
search_nickname + '@' + search_domain search_handle = \
search_nickname + '@' + search_domain
else:
search_handle = ''
else: else:
search_handle = '' search_handle = ''
if '@' not in search_handle: if '@' not in search_handle:
@ -2622,8 +2639,12 @@ class PubServer(BaseHTTPRequestHandler):
if search_nickname: if search_nickname:
search_domain, _ = \ search_domain, _ = \
get_domain_from_actor(search_handle) get_domain_from_actor(search_handle)
search_handle = \ if search_domain:
search_nickname + '@' + search_domain search_handle = \
search_nickname + '@' + \
search_domain
else:
search_handle = ''
else: else:
search_handle = '' search_handle = ''
if '@' not in search_handle: if '@' not in search_handle:
@ -2713,8 +2734,9 @@ class PubServer(BaseHTTPRequestHandler):
# https://domain # https://domain
block_domain, block_port = \ block_domain, block_port = \
get_domain_from_actor(moderation_domain) get_domain_from_actor(moderation_domain)
full_block_domain = \ if block_domain:
get_full_domain(block_domain, block_port) full_block_domain = \
get_full_domain(block_domain, block_port)
if '@' in moderation_domain: if '@' in moderation_domain:
# nick@domain or *@domain # nick@domain or *@domain
full_block_domain = \ full_block_domain = \
@ -2743,8 +2765,9 @@ class PubServer(BaseHTTPRequestHandler):
# https://domain # https://domain
block_domain, block_port = \ block_domain, block_port = \
get_domain_from_actor(moderation_domain) get_domain_from_actor(moderation_domain)
full_block_domain = \ if block_domain:
get_full_domain(block_domain, block_port) full_block_domain = \
get_full_domain(block_domain, block_port)
if '@' in moderation_domain: if '@' in moderation_domain:
# nick@domain or *@domain # nick@domain or *@domain
full_block_domain = moderation_domain.split('@')[1] full_block_domain = moderation_domain.split('@')[1]
@ -3144,6 +3167,16 @@ class PubServer(BaseHTTPRequestHandler):
return return
options_domain, options_port = get_domain_from_actor(options_actor) options_domain, options_port = get_domain_from_actor(options_actor)
if not options_domain:
if calling_domain.endswith('.onion') and onion_domain:
origin_path_str = 'http://' + onion_domain + users_path
elif (calling_domain.endswith('.i2p') and i2p_domain):
origin_path_str = 'http://' + i2p_domain + users_path
print('WARN: unable to find domain in ' + options_actor)
self._redirect_headers(origin_path_str, cookie, calling_domain)
self.server.postreq_busy = False
return
options_domain_full = get_full_domain(options_domain, options_port) options_domain_full = get_full_domain(options_domain, options_port)
if chooser_nickname == options_nickname and \ if chooser_nickname == options_nickname and \
options_domain == domain and \ options_domain == domain and \
@ -3942,13 +3975,13 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in following_actor: if '&' in following_actor:
following_actor = following_actor.split('&')[0] following_actor = following_actor.split('&')[0]
following_nickname = get_nickname_from_actor(following_actor) following_nickname = get_nickname_from_actor(following_actor)
if not following_nickname: following_domain, following_port = \
get_domain_from_actor(following_actor)
if not following_nickname or not following_domain:
self.send_response(400) self.send_response(400)
self.end_headers() self.end_headers()
self.server.postreq_busy = False self.server.postreq_busy = False
return return
following_domain, following_port = \
get_domain_from_actor(following_actor)
following_domain_full = \ following_domain_full = \
get_full_domain(following_domain, following_port) get_full_domain(following_domain, following_port)
if follower_nickname == following_nickname and \ if follower_nickname == following_nickname and \
@ -4051,13 +4084,13 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in following_actor: if '&' in following_actor:
following_actor = following_actor.split('&')[0] following_actor = following_actor.split('&')[0]
following_nickname = get_nickname_from_actor(following_actor) following_nickname = get_nickname_from_actor(following_actor)
if not following_nickname: following_domain, following_port = \
get_domain_from_actor(following_actor)
if not following_nickname or not following_domain:
self.send_response(400) self.send_response(400)
self.end_headers() self.end_headers()
self.server.postreq_busy = False self.server.postreq_busy = False
return return
following_domain, following_port = \
get_domain_from_actor(following_actor)
if follower_nickname == following_nickname and \ if follower_nickname == following_nickname and \
following_domain == domain and \ following_domain == domain and \
following_port == port: following_port == port:
@ -4128,19 +4161,19 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in blocking_actor: if '&' in blocking_actor:
blocking_actor = blocking_actor.split('&')[0] blocking_actor = blocking_actor.split('&')[0]
blocking_nickname = get_nickname_from_actor(blocking_actor) blocking_nickname = get_nickname_from_actor(blocking_actor)
if not blocking_nickname: blocking_domain, blocking_port = \
get_domain_from_actor(blocking_actor)
if not blocking_nickname or not blocking_domain:
if calling_domain.endswith('.onion') and onion_domain: if calling_domain.endswith('.onion') and onion_domain:
origin_path_str = 'http://' + onion_domain + users_path origin_path_str = 'http://' + onion_domain + users_path
elif (calling_domain.endswith('.i2p') and i2p_domain): elif (calling_domain.endswith('.i2p') and i2p_domain):
origin_path_str = 'http://' + i2p_domain + users_path origin_path_str = 'http://' + i2p_domain + users_path
print('WARN: unable to find blocked nickname in ' + print('WARN: unable to find blocked nickname or domain in ' +
blocking_actor) blocking_actor)
self._redirect_headers(origin_path_str, self._redirect_headers(origin_path_str,
cookie, calling_domain) cookie, calling_domain)
self.server.postreq_busy = False self.server.postreq_busy = False
return return
blocking_domain, blocking_port = \
get_domain_from_actor(blocking_actor)
blocking_domain_full = \ blocking_domain_full = \
get_full_domain(blocking_domain, blocking_port) get_full_domain(blocking_domain, blocking_port)
if follower_nickname == blocking_nickname and \ if follower_nickname == blocking_nickname and \
@ -4218,18 +4251,19 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in blocking_actor: if '&' in blocking_actor:
blocking_actor = blocking_actor.split('&')[0] blocking_actor = blocking_actor.split('&')[0]
blocking_nickname = get_nickname_from_actor(blocking_actor) blocking_nickname = get_nickname_from_actor(blocking_actor)
if not blocking_nickname: blocking_domain, blocking_port = \
get_domain_from_actor(blocking_actor)
if not blocking_nickname or not blocking_domain:
if calling_domain.endswith('.onion') and onion_domain: if calling_domain.endswith('.onion') and onion_domain:
origin_path_str = 'http://' + onion_domain + users_path origin_path_str = 'http://' + onion_domain + users_path
elif (calling_domain.endswith('.i2p') and i2p_domain): elif (calling_domain.endswith('.i2p') and i2p_domain):
origin_path_str = 'http://' + i2p_domain + users_path origin_path_str = 'http://' + i2p_domain + users_path
print('WARN: unable to find nickname in ' + blocking_actor) print('WARN: unable to find nickname or domain in ' +
blocking_actor)
self._redirect_headers(origin_path_str, self._redirect_headers(origin_path_str,
cookie, calling_domain) cookie, calling_domain)
self.server.postreq_busy = False self.server.postreq_busy = False
return return
blocking_domain, blocking_port = \
get_domain_from_actor(blocking_actor)
blocking_domain_full = \ blocking_domain_full = \
get_full_domain(blocking_domain, blocking_port) get_full_domain(blocking_domain, blocking_port)
if blocker_nickname == blocking_nickname and \ if blocker_nickname == blocking_nickname and \
@ -4310,7 +4344,9 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in blocking_actor: if '&' in blocking_actor:
blocking_actor = blocking_actor.split('&')[0] blocking_actor = blocking_actor.split('&')[0]
blocking_nickname = get_nickname_from_actor(blocking_actor) blocking_nickname = get_nickname_from_actor(blocking_actor)
if not blocking_nickname: blocking_domain, blocking_port = \
get_domain_from_actor(blocking_actor)
if not blocking_nickname or not blocking_domain:
if calling_domain.endswith('.onion') and onion_domain: if calling_domain.endswith('.onion') and onion_domain:
origin_path_str = 'http://' + onion_domain + users_path origin_path_str = 'http://' + onion_domain + users_path
elif (calling_domain.endswith('.i2p') and i2p_domain): elif (calling_domain.endswith('.i2p') and i2p_domain):
@ -4320,8 +4356,6 @@ class PubServer(BaseHTTPRequestHandler):
cookie, calling_domain) cookie, calling_domain)
self.server.postreq_busy = False self.server.postreq_busy = False
return return
blocking_domain, blocking_port = \
get_domain_from_actor(blocking_actor)
blocking_domain_full = \ blocking_domain_full = \
get_full_domain(blocking_domain, blocking_port) get_full_domain(blocking_domain, blocking_port)
if blocker_nickname == blocking_nickname and \ if blocker_nickname == blocking_nickname and \
@ -4692,13 +4726,13 @@ class PubServer(BaseHTTPRequestHandler):
# get the actor # get the actor
if not has_users_path(search_str): if not has_users_path(search_str):
search_nickname = get_nickname_from_actor(search_str) search_nickname = get_nickname_from_actor(search_str)
if not search_nickname: search_domain, search_port = \
get_domain_from_actor(search_str)
if not search_nickname or not search_domain:
self.send_response(400) self.send_response(400)
self.end_headers() self.end_headers()
self.server.postreq_busy = False self.server.postreq_busy = False
return return
search_domain, search_port = \
get_domain_from_actor(search_str)
search_domain_full = \ search_domain_full = \
get_full_domain(search_domain, search_port) get_full_domain(search_domain, search_port)
actor = \ actor = \
@ -5155,9 +5189,9 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in item_id: if '&' in item_id:
item_id = item_id.split('&')[0] item_id = item_id.split('&')[0]
share_nickname = get_nickname_from_actor(share_actor) share_nickname = get_nickname_from_actor(share_actor)
if share_nickname: share_domain, _ = \
share_domain, _ = \ get_domain_from_actor(share_actor)
get_domain_from_actor(share_actor) if share_nickname and share_domain:
remove_shared_item(base_dir, remove_shared_item(base_dir,
share_nickname, share_domain, item_id, share_nickname, share_domain, item_id,
'shares') 'shares')
@ -5227,9 +5261,9 @@ class PubServer(BaseHTTPRequestHandler):
if '&' in item_id: if '&' in item_id:
item_id = item_id.split('&')[0] item_id = item_id.split('&')[0]
share_nickname = get_nickname_from_actor(share_actor) share_nickname = get_nickname_from_actor(share_actor)
if share_nickname: share_domain, _ = \
share_domain, _ = \ get_domain_from_actor(share_actor)
get_domain_from_actor(share_actor) if share_nickname and share_domain:
remove_shared_item(base_dir, remove_shared_item(base_dir,
share_nickname, share_domain, item_id, share_nickname, share_domain, item_id,
'wanted') 'wanted')
@ -9730,11 +9764,11 @@ class PubServer(BaseHTTPRequestHandler):
following_handle = path.split('/followapprove=')[1] following_handle = path.split('/followapprove=')[1]
if '://' in following_handle: if '://' in following_handle:
handle_nickname = get_nickname_from_actor(following_handle) handle_nickname = get_nickname_from_actor(following_handle)
if not handle_nickname:
self._404()
return
handle_domain, handle_port = \ handle_domain, handle_port = \
get_domain_from_actor(following_handle) get_domain_from_actor(following_handle)
if not handle_nickname or not handle_domain:
self._404()
return
following_handle = \ following_handle = \
handle_nickname + '@' + \ handle_nickname + '@' + \
get_full_domain(handle_domain, handle_port) get_full_domain(handle_domain, handle_port)
@ -9912,11 +9946,11 @@ class PubServer(BaseHTTPRequestHandler):
following_handle = path.split('/followdeny=')[1] following_handle = path.split('/followdeny=')[1]
if '://' in following_handle: if '://' in following_handle:
handle_nickname = get_nickname_from_actor(following_handle) handle_nickname = get_nickname_from_actor(following_handle)
if not handle_nickname:
self._404()
return
handle_domain, handle_port = \ handle_domain, handle_port = \
get_domain_from_actor(following_handle) get_domain_from_actor(following_handle)
if not handle_nickname or not handle_domain:
self._404()
return
following_handle = \ following_handle = \
handle_nickname + '@' + \ handle_nickname + '@' + \
get_full_domain(handle_domain, handle_port) get_full_domain(handle_domain, handle_port)

View File

@ -1386,7 +1386,11 @@ def _desktop_show_follow_requests(follow_requests_json: {},
print('') print('')
for item in follow_requests_json['orderedItems']: for item in follow_requests_json['orderedItems']:
handle_nickname = get_nickname_from_actor(item) handle_nickname = get_nickname_from_actor(item)
if not handle_nickname:
continue
handle_domain, handle_port = get_domain_from_actor(item) handle_domain, handle_port = get_domain_from_actor(item)
if not handle_domain:
continue
handle_domain_full = \ handle_domain_full = \
get_full_domain(handle_domain, handle_port) get_full_domain(handle_domain, handle_port)
print(indent + ' 👤 ' + print(indent + ' 👤 ' +
@ -1412,7 +1416,11 @@ def _desktop_show_following(following_json: {}, translate: {},
print('') print('')
for item in following_json['orderedItems']: for item in following_json['orderedItems']:
handle_nickname = get_nickname_from_actor(item) handle_nickname = get_nickname_from_actor(item)
if not handle_nickname:
continue
handle_domain, handle_port = get_domain_from_actor(item) handle_domain, handle_port = get_domain_from_actor(item)
if not handle_domain:
continue
handle_domain_full = \ handle_domain_full = \
get_full_domain(handle_domain, handle_port) get_full_domain(handle_domain, handle_port)
print(indent + ' 👤 ' + print(indent + ' 👤 ' +

View File

@ -191,6 +191,9 @@ def is_following_actor(base_dir: str,
print('WARN: unable to find nickname in ' + actor) print('WARN: unable to find nickname in ' + actor)
return False return False
following_domain, following_port = get_domain_from_actor(actor) following_domain, following_port = get_domain_from_actor(actor)
if not following_domain:
print('WARN: unable to find domain in ' + actor)
return False
following_handle = \ following_handle = \
get_full_domain(following_nickname + '@' + following_domain, get_full_domain(following_nickname + '@' + following_domain,
following_port) following_port)
@ -1437,6 +1440,10 @@ def outbox_undo_follow(base_dir: str, message_json: {}, debug: bool) -> None:
return return
domain_follower, port_follower = \ domain_follower, port_follower = \
get_domain_from_actor(message_json['object']['actor']) get_domain_from_actor(message_json['object']['actor'])
if not domain_follower:
print('WARN: unable to find domain in ' +
message_json['object']['actor'])
return
domain_follower_full = get_full_domain(domain_follower, port_follower) domain_follower_full = get_full_domain(domain_follower, port_follower)
nickname_following = \ nickname_following = \
@ -1447,6 +1454,10 @@ def outbox_undo_follow(base_dir: str, message_json: {}, debug: bool) -> None:
return return
domain_following, port_following = \ domain_following, port_following = \
get_domain_from_actor(message_json['object']['object']) get_domain_from_actor(message_json['object']['object'])
if not domain_following:
print('WARN: unable to find domain in ' +
message_json['object']['object'])
return
domain_following_full = get_full_domain(domain_following, port_following) domain_following_full = get_full_domain(domain_following, port_following)
group_account = \ group_account = \

138
inbox.py
View File

@ -674,12 +674,14 @@ def save_post_to_inbox_queue(base_dir: str, http_prefix: str,
post_json_object['object']['inReplyTo'] post_json_object['object']['inReplyTo']
reply_domain, _ = \ reply_domain, _ = \
get_domain_from_actor(in_reply_to) get_domain_from_actor(in_reply_to)
if is_blocked_domain(base_dir, reply_domain, blocked_cache): if reply_domain:
if debug: if is_blocked_domain(base_dir, reply_domain,
print('WARN: post contains reply from ' + blocked_cache):
str(actor) + if debug:
' to a blocked domain: ' + reply_domain) print('WARN: post contains reply from ' +
return None str(actor) +
' to a blocked domain: ' + reply_domain)
return None
reply_nickname = \ reply_nickname = \
get_nickname_from_actor(in_reply_to) get_nickname_from_actor(in_reply_to)
@ -974,6 +976,10 @@ def _receive_undo_follow(base_dir: str, message_json: {},
return False return False
domain_follower, port_follower = \ domain_follower, port_follower = \
get_domain_from_actor(message_json['object']['actor']) get_domain_from_actor(message_json['object']['actor'])
if not domain_follower:
print('WARN: unable to find domain in ' +
message_json['object']['actor'])
return False
domain_follower_full = get_full_domain(domain_follower, port_follower) domain_follower_full = get_full_domain(domain_follower, port_follower)
nickname_following = \ nickname_following = \
@ -984,6 +990,10 @@ def _receive_undo_follow(base_dir: str, message_json: {},
return False return False
domain_following, port_following = \ domain_following, port_following = \
get_domain_from_actor(message_json['object']['object']) get_domain_from_actor(message_json['object']['object'])
if not domain_following:
print('WARN: unable to find domain in ' +
message_json['object']['object'])
return False
if onion_domain: if onion_domain:
if domain_following.endswith(onion_domain): if domain_following.endswith(onion_domain):
domain_following = domain domain_following = domain
@ -1149,46 +1159,51 @@ def _person_receive_update(base_dir: str,
print('actor updated for ' + person_json['id']) print('actor updated for ' + person_json['id'])
if person_json.get('movedTo'): if person_json.get('movedTo'):
prev_domain_full = None
prev_domain, prev_port = get_domain_from_actor(person_json['id']) prev_domain, prev_port = get_domain_from_actor(person_json['id'])
prev_domain_full = get_full_domain(prev_domain, prev_port) if prev_domain:
prev_domain_full = get_full_domain(prev_domain, prev_port)
prev_nickname = get_nickname_from_actor(person_json['id']) prev_nickname = get_nickname_from_actor(person_json['id'])
new_domain = None
new_domain, new_port = get_domain_from_actor(person_json['movedTo']) new_domain, new_port = get_domain_from_actor(person_json['movedTo'])
new_domain_full = get_full_domain(new_domain, new_port) if new_domain:
new_domain_full = get_full_domain(new_domain, new_port)
new_nickname = get_nickname_from_actor(person_json['movedTo']) new_nickname = get_nickname_from_actor(person_json['movedTo'])
new_actor = prev_nickname + '@' + prev_domain_full + ' ' + \ if prev_domain_full and new_domain:
new_nickname + '@' + new_domain_full new_actor = prev_nickname + '@' + prev_domain_full + ' ' + \
refollow_str = '' new_nickname + '@' + new_domain_full
refollow_filename = base_dir + '/accounts/actors_moved.txt' refollow_str = ''
refollow_file_exists = False refollow_filename = base_dir + '/accounts/actors_moved.txt'
if os.path.isfile(refollow_filename): refollow_file_exists = False
try: if os.path.isfile(refollow_filename):
with open(refollow_filename, 'r', try:
encoding='utf-8') as fp_refollow: with open(refollow_filename, 'r',
refollow_str = fp_refollow.read() encoding='utf-8') as fp_refollow:
refollow_file_exists = True refollow_str = fp_refollow.read()
except OSError: refollow_file_exists = True
print('EX: unable to read ' + refollow_filename) except OSError:
if new_actor not in refollow_str: print('EX: unable to read ' + refollow_filename)
refollow_type = 'w+' if new_actor not in refollow_str:
if refollow_file_exists: refollow_type = 'w+'
refollow_type = 'a+' if refollow_file_exists:
try: refollow_type = 'a+'
with open(refollow_filename, refollow_type, try:
encoding='utf-8') as fp_refollow: with open(refollow_filename, refollow_type,
fp_refollow.write(new_actor + '\n') encoding='utf-8') as fp_refollow:
except OSError: fp_refollow.write(new_actor + '\n')
print('EX: unable to write to ' + except OSError:
refollow_filename) print('EX: unable to write to ' +
prev_avatar_url = \ refollow_filename)
get_person_avatar_url(base_dir, person_json['id'], prev_avatar_url = \
person_cache) get_person_avatar_url(base_dir, person_json['id'],
if prev_avatar_url is None: person_cache)
prev_avatar_url = '' if prev_avatar_url is None:
_notify_moved(base_dir, domain_full, prev_avatar_url = ''
prev_nickname + '@' + prev_domain_full, _notify_moved(base_dir, domain_full,
new_nickname + '@' + new_domain_full, prev_nickname + '@' + prev_domain_full,
person_json['id'], prev_avatar_url, http_prefix) new_nickname + '@' + new_domain_full,
person_json['id'], prev_avatar_url, http_prefix)
# remove avatar if it exists so that it will be refreshed later # remove avatar if it exists so that it will be refreshed later
# when a timeline is constructed # when a timeline is constructed
@ -1476,9 +1491,9 @@ def _receive_update_activity(recent_posts_cache: {}, session, base_dir: str,
if debug: if debug:
print('Request to update actor: ' + str(message_json)) print('Request to update actor: ' + str(message_json))
update_nickname = get_nickname_from_actor(message_json['actor']) update_nickname = get_nickname_from_actor(message_json['actor'])
if update_nickname: update_domain, update_port = \
update_domain, update_port = \ get_domain_from_actor(message_json['actor'])
get_domain_from_actor(message_json['actor']) if update_nickname and update_domain:
if _person_receive_update(base_dir, if _person_receive_update(base_dir,
domain, port, domain, port,
update_nickname, update_domain, update_nickname, update_domain,
@ -2648,6 +2663,9 @@ def _receive_announce(recent_posts_cache: {},
print('WARN: _receive_announce no actor_nickname') print('WARN: _receive_announce no actor_nickname')
return False return False
actor_domain, _ = get_domain_from_actor(message_json['actor']) actor_domain, _ = get_domain_from_actor(message_json['actor'])
if not actor_domain:
print('WARN: _receive_announce no actor_domain')
return False
if is_blocked(base_dir, nickname, domain, actor_nickname, actor_domain): if is_blocked(base_dir, nickname, domain, actor_nickname, actor_domain):
print('Receive announce blocked for actor: ' + print('Receive announce blocked for actor: ' +
actor_nickname + '@' + actor_domain) actor_nickname + '@' + actor_domain)
@ -2666,6 +2684,9 @@ def _receive_announce(recent_posts_cache: {},
print('WARN: _receive_announce no announced_actor_nickname') print('WARN: _receive_announce no announced_actor_nickname')
return False return False
announced_actor_domain, _ = get_domain_from_actor(message_json['object']) announced_actor_domain, _ = get_domain_from_actor(message_json['object'])
if not announced_actor_domain:
print('WARN: _receive_announce no announced_actor_domain')
return False
if is_blocked(base_dir, nickname, domain, if is_blocked(base_dir, nickname, domain,
announced_actor_nickname, announced_actor_domain): announced_actor_nickname, announced_actor_domain):
print('Receive announce object blocked for actor: ' + print('Receive announce object blocked for actor: ' +
@ -3588,6 +3609,8 @@ def _inbox_update_calendar(base_dir: str, handle: str,
if not actor_nickname: if not actor_nickname:
return return
actor_domain, _ = get_domain_from_actor(actor) actor_domain, _ = get_domain_from_actor(actor)
if not actor_domain:
return
handle_nickname = handle.split('@')[0] handle_nickname = handle.split('@')[0]
handle_domain = handle.split('@')[1] handle_domain = handle.split('@')[1]
if not receiving_calendar_events(base_dir, if not receiving_calendar_events(base_dir,
@ -4086,6 +4109,8 @@ def _low_frequency_post_notification(base_dir: str, http_prefix: str,
if not from_nickname: if not from_nickname:
return return
from_domain, from_port = get_domain_from_actor(attributed_to) from_domain, from_port = get_domain_from_actor(attributed_to)
if not from_domain:
return
from_domain_full = get_full_domain(from_domain, from_port) from_domain_full = get_full_domain(from_domain, from_port)
if notify_when_person_posts(base_dir, nickname, domain, if notify_when_person_posts(base_dir, nickname, domain,
from_nickname, from_domain_full): from_nickname, from_domain_full):
@ -4116,6 +4141,8 @@ def _check_for_git_patches(base_dir: str, nickname: str, domain: str,
if not from_nickname: if not from_nickname:
return 0 return 0
from_domain, from_port = get_domain_from_actor(attributed_to) from_domain, from_port = get_domain_from_actor(attributed_to)
if not from_domain:
return 0
from_domain_full = get_full_domain(from_domain, from_port) from_domain_full = get_full_domain(from_domain, from_port)
if receive_git_patch(base_dir, nickname, domain, if receive_git_patch(base_dir, nickname, domain,
json_obj['type'], json_obj['summary'], json_obj['type'], json_obj['summary'],
@ -5144,6 +5171,11 @@ def _receive_follow_request(session, session_onion, session_i2p,
'users/profile/author/accounts/channel missing from actor') 'users/profile/author/accounts/channel missing from actor')
return False return False
domain, temp_port = get_domain_from_actor(message_json['actor']) domain, temp_port = get_domain_from_actor(message_json['actor'])
if not domain:
if debug:
print('DEBUG: receive follow request actor without domain ' +
message_json['actor'])
return False
from_port = port from_port = port
domain_full = get_full_domain(domain, temp_port) domain_full = get_full_domain(domain, temp_port)
if temp_port: if temp_port:
@ -5167,6 +5199,11 @@ def _receive_follow_request(session, session_onion, session_i2p,
'not found within object') 'not found within object')
return False return False
domain_to_follow, temp_port = get_domain_from_actor(message_json['object']) domain_to_follow, temp_port = get_domain_from_actor(message_json['object'])
if not domain_to_follow:
if debug:
print('DEBUG: receive follow request no domain found in object ' +
message_json['object'])
return False
# switch to the local domain rather than its onion or i2p version # switch to the local domain rather than its onion or i2p version
if onion_domain: if onion_domain:
if domain_to_follow.endswith(onion_domain): if domain_to_follow.endswith(onion_domain):
@ -5613,12 +5650,13 @@ def run_inbox_queue(server,
if queue_json.get('actor'): if queue_json.get('actor'):
if isinstance(queue_json['actor'], str): if isinstance(queue_json['actor'], str):
sender_domain, _ = get_domain_from_actor(queue_json['actor']) sender_domain, _ = get_domain_from_actor(queue_json['actor'])
if sender_domain.endswith('.onion') and \ if sender_domain:
session_onion and proxy_type != 'tor': if sender_domain.endswith('.onion') and \
curr_session = session_onion session_onion and proxy_type != 'tor':
elif (sender_domain.endswith('.i2p') and curr_session = session_onion
session_i2p and proxy_type != 'i2p'): elif (sender_domain.endswith('.i2p') and
curr_session = session_i2p session_i2p and proxy_type != 'i2p'):
curr_session = session_i2p
if debug and queue_json.get('actor'): if debug and queue_json.get('actor'):
print('Obtaining public key for actor ' + queue_json['actor']) print('Obtaining public key for actor ' + queue_json['actor'])

14
like.py
View File

@ -114,12 +114,14 @@ def _create_like(recent_posts_cache: {},
liked_post_nickname = get_nickname_from_actor(object_url) liked_post_nickname = get_nickname_from_actor(object_url)
liked_post_domain, liked_post_port = \ liked_post_domain, liked_post_port = \
get_domain_from_actor(object_url) get_domain_from_actor(object_url)
if '/' + str(liked_post_nickname) + '/' in object_url: if liked_post_nickname and liked_post_domain:
actor_liked = \ if '/' + str(liked_post_nickname) + '/' in object_url:
object_url.split('/' + liked_post_nickname + '/')[0] + \ actor_liked = \
'/' + liked_post_nickname object_url.split('/' +
group_account = \ liked_post_nickname + '/')[0] + \
has_group_type(base_dir, actor_liked, person_cache) '/' + liked_post_nickname
group_account = \
has_group_type(base_dir, actor_liked, person_cache)
if liked_post_nickname: if liked_post_nickname:
post_filename = locate_post(base_dir, nickname, domain, object_url) post_filename = locate_post(base_dir, nickname, domain, object_url)

View File

@ -275,6 +275,8 @@ def post_message_to_outbox(session, translate: {},
if isinstance(message_json['object']['to'], list): if isinstance(message_json['object']['to'], list):
for to_actor in message_json['object']['to']: for to_actor in message_json['object']['to']:
to_domain, to_port = get_domain_from_actor(to_actor) to_domain, to_port = get_domain_from_actor(to_actor)
if not to_domain:
continue
to_domain_full = get_full_domain(to_domain, to_port) to_domain_full = get_full_domain(to_domain, to_port)
if domain_full != to_domain_full: if domain_full != to_domain_full:
print("REJECT: local only post isn't local " + print("REJECT: local only post isn't local " +
@ -283,11 +285,13 @@ def post_message_to_outbox(session, translate: {},
# check that the sender is local # check that the sender is local
local_actor = message_json['object']['attributedTo'] local_actor = message_json['object']['attributedTo']
local_domain, local_port = get_domain_from_actor(local_actor) local_domain, local_port = get_domain_from_actor(local_actor)
local_domain_full = get_full_domain(local_domain, local_port) if local_domain:
if domain_full != local_domain_full: local_domain_full = \
print("REJECT: local only post isn't local " + get_full_domain(local_domain, local_port)
str(message_json)) if domain_full != local_domain_full:
return False print("REJECT: local only post isn't local " +
str(message_json))
return False
if is_quote_toot(message_json, ''): if is_quote_toot(message_json, ''):
print('REJECT: POST quote toot ' + str(message_json)) print('REJECT: POST quote toot ' + str(message_json))
@ -357,11 +361,12 @@ def post_message_to_outbox(session, translate: {},
return False return False
test_domain, test_port = get_domain_from_actor(message_json['actor']) test_domain, test_port = get_domain_from_actor(message_json['actor'])
test_domain = get_full_domain(test_domain, test_port) if test_domain:
if is_blocked_domain(base_dir, test_domain): test_domain = get_full_domain(test_domain, test_port)
if debug: if is_blocked_domain(base_dir, test_domain):
print('DEBUG: domain is blocked: ' + message_json['actor']) if debug:
return False print('DEBUG: domain is blocked: ' + message_json['actor'])
return False
# replace youtube, so that google gets less tracking data # replace youtube, so that google gets less tracking data
replace_you_tube(message_json, yt_replace_domain, system_language) replace_you_tube(message_json, yt_replace_domain, system_language)
# replace twitter, so that twitter posts can be shown without # replace twitter, so that twitter posts can be shown without

View File

@ -760,8 +760,9 @@ def get_post_domains(session, outbox_url: str, max_posts: int, debug: bool,
if isinstance(item['object']['inReplyTo'], str): if isinstance(item['object']['inReplyTo'], str):
post_domain, _ = \ post_domain, _ = \
get_domain_from_actor(item['object']['inReplyTo']) get_domain_from_actor(item['object']['inReplyTo'])
if post_domain not in post_domains: if post_domain:
post_domains.append(post_domain) if post_domain not in post_domains:
post_domains.append(post_domain)
if item['object'].get('tag'): if item['object'].get('tag'):
for tag_item in item['object']['tag']: for tag_item in item['object']['tag']:
@ -772,8 +773,9 @@ def get_post_domains(session, outbox_url: str, max_posts: int, debug: bool,
if tag_item.get('href'): if tag_item.get('href'):
post_domain, _ = \ post_domain, _ = \
get_domain_from_actor(tag_item['href']) get_domain_from_actor(tag_item['href'])
if post_domain not in post_domains: if post_domain:
post_domains.append(post_domain) if post_domain not in post_domains:
post_domains.append(post_domain)
return post_domains return post_domains
@ -818,6 +820,8 @@ def _get_posts_for_blocked_domains(base_dir: str,
if isinstance(item['object']['inReplyTo'], str): if isinstance(item['object']['inReplyTo'], str):
post_domain, _ = \ post_domain, _ = \
get_domain_from_actor(item['object']['inReplyTo']) get_domain_from_actor(item['object']['inReplyTo'])
if not post_domain:
continue
if is_blocked_domain(base_dir, post_domain): if is_blocked_domain(base_dir, post_domain):
if item['object'].get('url'): if item['object'].get('url'):
url = item['object']['url'] url = item['object']['url']
@ -837,6 +841,8 @@ def _get_posts_for_blocked_domains(base_dir: str,
if tag_type == 'mention' and tag_item.get('href'): if tag_type == 'mention' and tag_item.get('href'):
post_domain, _ = \ post_domain, _ = \
get_domain_from_actor(tag_item['href']) get_domain_from_actor(tag_item['href'])
if not post_domain:
continue
if is_blocked_domain(base_dir, post_domain): if is_blocked_domain(base_dir, post_domain):
if item['object'].get('url'): if item['object'].get('url'):
url = item['object']['url'] url = item['object']['url']
@ -1084,6 +1090,11 @@ def _create_post_cw_from_reply(base_dir: str, nickname: str, domain: str,
def _attach_post_license(post_json_object: {}, def _attach_post_license(post_json_object: {},
content_license_url: str) -> None: content_license_url: str) -> None:
"""Attaches a license to each post """Attaches a license to each post
Also see:
https://codeberg.org/fediverse/fep/src/branch/main/feps/fep-c118.md
NOTE: at present (Jan 2023) there is no consensus about how to
represent license information on ActivityPub posts, so this might
need to change if such a consensus appears.
""" """
post_json_object['attachment'].append({ post_json_object['attachment'].append({
"type": "PropertyValue", "type": "PropertyValue",
@ -1285,7 +1296,15 @@ def _create_post_place_and_time(event_date: str, end_date: str,
end_date_str = end_date + 'T' + end_time + \ end_date_str = end_date + 'T' + end_time + \
':00' + strftime("%z", gmtime()) ':00' + strftime("%z", gmtime())
else: else:
end_date_str = end_date + 'T12:00:00Z' if not event_time:
end_date_str = end_date + 'T12:00:00Z'
else:
if event_time.endswith('Z'):
end_date_str = end_date + 'T' + event_time
else:
end_date_str = \
end_date + 'T' + event_time + ':00' + \
strftime("%z", gmtime())
# get the starting date and time # get the starting date and time
event_date_str = None event_date_str = None

View File

@ -113,12 +113,14 @@ def _reactionpost(recent_posts_cache: {},
reaction_post_nickname = get_nickname_from_actor(object_url) reaction_post_nickname = get_nickname_from_actor(object_url)
reaction_post_domain, reaction_post_port = \ reaction_post_domain, reaction_post_port = \
get_domain_from_actor(object_url) get_domain_from_actor(object_url)
if '/' + str(reaction_post_nickname) + '/' in object_url: if reaction_post_domain:
actor_reaction = \ if '/' + str(reaction_post_nickname) + '/' in object_url:
object_url.split('/' + reaction_post_nickname + '/')[0] + \ actor_reaction = \
'/' + reaction_post_nickname object_url.split('/' +
group_account = \ reaction_post_nickname + '/')[0] + \
has_group_type(base_dir, actor_reaction, person_cache) '/' + reaction_post_nickname
group_account = \
has_group_type(base_dir, actor_reaction, person_cache)
if reaction_post_nickname: if reaction_post_nickname:
post_filename = locate_post(base_dir, nickname, domain, object_url) post_filename = locate_post(base_dir, nickname, domain, object_url)
@ -595,6 +597,8 @@ def html_emoji_reactions(post_json_object: {}, interactive: bool,
if not emoji_nickname: if not emoji_nickname:
return '' return ''
emoji_domain, _ = get_domain_from_actor(emoji_actor) emoji_domain, _ = get_domain_from_actor(emoji_actor)
if not emoji_domain:
return ''
emoji_handle = emoji_nickname + '@' + emoji_domain emoji_handle = emoji_nickname + '@' + emoji_domain
if emoji_actor == actor: if emoji_actor == actor:
if emoji_content not in reacted_to_by_this_actor: if emoji_content not in reacted_to_by_this_actor:

View File

@ -208,6 +208,8 @@ def update_moved_actors(base_dir: str, debug: bool) -> None:
actor_str = actor_str.replace('.json', '').replace('#', '/') actor_str = actor_str.replace('.json', '').replace('#', '/')
nickname = get_nickname_from_actor(actor_str) nickname = get_nickname_from_actor(actor_str)
domain, port = get_domain_from_actor(actor_str) domain, port = get_domain_from_actor(actor_str)
if not domain:
continue
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
handle = nickname + '@' + domain_full handle = nickname + '@' + domain_full
actors_dict[handle] = orig_str actors_dict[handle] = orig_str

View File

@ -4223,6 +4223,15 @@ def license_link_from_name(license: str) -> str:
value = 'https://www.gnu.org/licenses/fdl-1.3.html' value = 'https://www.gnu.org/licenses/fdl-1.3.html'
elif 'OPL' in value_upper or 'OPEN PUBLICATION LIC' in value_upper: elif 'OPL' in value_upper or 'OPEN PUBLICATION LIC' in value_upper:
value = 'https://opencontent.org/openpub' value = 'https://opencontent.org/openpub'
elif 'PDDL' in value_upper or 'OPEN DATA COMMONS PUBLIC' in value_upper:
value = 'https://opendatacommons.org/licenses/pddl'
elif 'ODBL' in value_upper or 'OPEN DATA COMMONS OPEN' in value_upper:
value = 'https://opendatacommons.org/licenses/odbl'
elif 'ODC' in value_upper or 'OPEN DATA COMMONS ATTR' in value_upper:
value = 'https://opendatacommons.org/licenses/by'
elif 'OGL' in value_upper or 'OPEN GOVERNMENT LIC' in value_upper:
value = \
'https://www.nationalarchives.gov.uk/doc/open-government-licence'
elif 'PDL' in value_upper or \ elif 'PDL' in value_upper or \
'PUBLIC DOCUMENTATION LIC' in value_upper: 'PUBLIC DOCUMENTATION LIC' in value_upper:
value = 'http://www.openoffice.org/licenses/PDL.html' value = 'http://www.openoffice.org/licenses/PDL.html'

View File

@ -49,6 +49,8 @@ def html_calendar_delete_confirm(translate: {}, base_dir: str,
return None return None
actor = local_actor_url(http_prefix, nickname, domain_full) actor = local_actor_url(http_prefix, nickname, domain_full)
domain, _ = get_domain_from_actor(actor) domain, _ = get_domain_from_actor(actor)
if not domain:
return None
message_id = actor + '/statuses/' + post_id message_id = actor + '/statuses/' + post_id
post_filename = locate_post(base_dir, nickname, domain, message_id) post_filename = locate_post(base_dir, nickname, domain, message_id)
@ -171,6 +173,7 @@ def _html_calendar_day(person_cache: {}, translate: {},
if day_events: if day_events:
for event_post in day_events: for event_post in day_events:
event_time = None event_time = None
event_time_markup = None
event_end_time = None event_end_time = None
start_time_str = '' start_time_str = ''
end_time_str = '' end_time_str = ''
@ -272,20 +275,27 @@ def _html_calendar_day(person_cache: {}, translate: {},
event_class = 'calendar__day__event__public__rtl' event_class = 'calendar__day__event__public__rtl'
cal_item_class = 'calItemPublic' cal_item_class = 'calItemPublic'
if event_time: if event_time:
if event_end_time: event_time_markup = \
event_time = \ '<time datetime="' + start_time_str + '">' + \
'<time datetime="' + start_time_str + '">' + \ event_time + '</time>'
event_time + '</time> - ' + \ if event_time and event_end_time and \
'<time datetime="' + end_time_str + '">' + \ start_time_str != end_time_str:
event_end_time + '</time>' event_time_int_str = event_time.replace(':', '')
else: event_end_time_int_str = event_end_time.replace(':', '')
event_time = \ if event_time_int_str.isdigit() and \
'<time datetime="' + start_time_str + '">' + \ event_end_time_int_str.isdigit():
event_time + '</time>' if int(event_end_time_int_str) > \
int(event_time_int_str):
event_time_markup = \
'<time datetime="' + start_time_str + '">' + \
event_time_markup + '</time> - ' + \
'<time datetime="' + end_time_str + '">' + \
event_end_time + '</time>'
if event_time and event_description and event_place: if event_time and event_description and event_place:
calendar_str += \ calendar_str += \
'<tr class="' + cal_item_class + '">' + \ '<tr class="' + cal_item_class + '">' + \
'<td class="calendar__day__time"><b>' + event_time + \ '<td class="calendar__day__time"><b>' + \
event_time_markup + \
'</b></td><td class="' + event_class + '">' + \ '</b></td><td class="' + event_class + '">' + \
'<span class="place">' + \ '<span class="place">' + \
event_place + '</span><br>' + event_description + \ event_place + '</span><br>' + event_description + \
@ -293,7 +303,8 @@ def _html_calendar_day(person_cache: {}, translate: {},
elif event_time and event_description and not event_place: elif event_time and event_description and not event_place:
calendar_str += \ calendar_str += \
'<tr class="' + cal_item_class + '">' + \ '<tr class="' + cal_item_class + '">' + \
'<td class="calendar__day__time"><b>' + event_time + \ '<td class="calendar__day__time"><b>' + \
event_time_markup + \
'</b></td><td class="' + event_class + '">' + \ '</b></td><td class="' + event_class + '">' + \
event_description + '</td>' + delete_button_str + '</tr>\n' event_description + '</td>' + delete_button_str + '</tr>\n'
elif not event_time and event_description and not event_place: elif not event_time and event_description and not event_place:
@ -312,7 +323,8 @@ def _html_calendar_day(person_cache: {}, translate: {},
elif event_time and not event_description and event_place: elif event_time and not event_description and event_place:
calendar_str += \ calendar_str += \
'<tr class="' + cal_item_class + '">' + \ '<tr class="' + cal_item_class + '">' + \
'<td class="calendar__day__time"><b>' + event_time + \ '<td class="calendar__day__time"><b>' + \
event_time_markup + \
'</b></td><td class="' + event_class + '">' + \ '</b></td><td class="' + event_class + '">' + \
'<span class="place">' + \ '<span class="place">' + \
event_place + '</span></td>' + \ event_place + '</span></td>' + \

View File

@ -51,6 +51,8 @@ def html_confirm_delete(server,
if not nickname: if not nickname:
return None return None
domain, port = get_domain_from_actor(actor) domain, port = get_domain_from_actor(actor)
if not domain:
return None
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
post_filename = locate_post(base_dir, nickname, domain, message_id) post_filename = locate_post(base_dir, nickname, domain, message_id)
@ -135,6 +137,8 @@ def html_confirm_remove_shared_item(translate: {},
if not nickname: if not nickname:
return None return None
domain, port = get_domain_from_actor(actor) domain, port = get_domain_from_actor(actor)
if not domain:
return None
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
shares_file = \ shares_file = \
acct_dir(base_dir, nickname, domain) + '/' + shares_file_type + '.json' acct_dir(base_dir, nickname, domain) + '/' + shares_file_type + '.json'
@ -224,7 +228,7 @@ def html_confirm_follow(translate: {}, base_dir: str,
' <img loading="lazy" decoding="async" ' + \ ' <img loading="lazy" decoding="async" ' + \
'src="' + follow_profile_url + '"/></a>\n' 'src="' + follow_profile_url + '"/></a>\n'
follow_actor_nick = get_nickname_from_actor(follow_actor) follow_actor_nick = get_nickname_from_actor(follow_actor)
if follow_actor_nick: if follow_actor_nick and follow_domain:
follow_str += \ follow_str += \
' <p class="followText">' + translate['Follow'] + ' ' + \ ' <p class="followText">' + translate['Follow'] + ' ' + \
follow_actor_nick + '@' + follow_domain + ' ?</p>\n' follow_actor_nick + '@' + follow_domain + ' ?</p>\n'
@ -274,7 +278,7 @@ def html_confirm_unfollow(translate: {}, base_dir: str,
' <img loading="lazy" decoding="async" src="' + \ ' <img loading="lazy" decoding="async" src="' + \
follow_profile_url + '"/></a>\n' follow_profile_url + '"/></a>\n'
follow_actor_nick = get_nickname_from_actor(follow_actor) follow_actor_nick = get_nickname_from_actor(follow_actor)
if follow_actor_nick: if follow_actor_nick and follow_domain:
follow_str += \ follow_str += \
' <p class="followText">' + translate['Stop following'] + \ ' <p class="followText">' + translate['Stop following'] + \
' ' + follow_actor_nick + '@' + follow_domain + ' ?</p>\n' ' ' + follow_actor_nick + '@' + follow_domain + ' ?</p>\n'
@ -321,7 +325,7 @@ def html_confirm_unblock(translate: {}, base_dir: str,
' <img loading="lazy" decoding="async" src="' + \ ' <img loading="lazy" decoding="async" src="' + \
block_profile_url + '"/></a>\n' block_profile_url + '"/></a>\n'
block_actor_nick = get_nickname_from_actor(block_actor) block_actor_nick = get_nickname_from_actor(block_actor)
if block_actor_nick: if block_actor_nick and block_domain:
block_str += \ block_str += \
' <p class="blockText">' + translate['Stop blocking'] + ' ' + \ ' <p class="blockText">' + translate['Stop blocking'] + ' ' + \
block_actor_nick + '@' + block_domain + ' ?</p>\n' block_actor_nick + '@' + block_domain + ' ?</p>\n'
@ -368,7 +372,7 @@ def html_confirm_block(translate: {}, base_dir: str,
' <img loading="lazy" decoding="async" src="' + \ ' <img loading="lazy" decoding="async" src="' + \
block_profile_url + '"/></a>\n' block_profile_url + '"/></a>\n'
block_actor_nick = get_nickname_from_actor(block_actor) block_actor_nick = get_nickname_from_actor(block_actor)
if block_actor_nick: if block_actor_nick and block_domain:
block_str += \ block_str += \
' <p class="blockText">' + translate['Block'] + ' ' + \ ' <p class="blockText">' + translate['Block'] + ' ' + \
block_actor_nick + '@' + block_domain + ' ?</p>\n' block_actor_nick + '@' + block_domain + ' ?</p>\n'

View File

@ -119,6 +119,8 @@ def html_account_info(translate: {},
if not search_nickname: if not search_nickname:
return '' return ''
search_domain, search_port = get_domain_from_actor(search_handle) search_domain, search_port = get_domain_from_actor(search_handle)
if not search_domain:
return ''
search_handle = search_nickname + '@' + search_domain search_handle = search_nickname + '@' + search_domain
search_actor = \ search_actor = \
@ -160,6 +162,8 @@ def html_account_info(translate: {},
if not follower_nickname: if not follower_nickname:
return '' return ''
follower_domain, follower_port = get_domain_from_actor(follower_actor) follower_domain, follower_port = get_domain_from_actor(follower_actor)
if not follower_domain:
return ''
follower_domain_full = get_full_domain(follower_domain, follower_port) follower_domain_full = get_full_domain(follower_domain, follower_port)
if is_blocked(base_dir, nickname, domain, if is_blocked(base_dir, nickname, domain,
follower_nickname, follower_domain_full): follower_nickname, follower_domain_full):
@ -177,6 +181,8 @@ def html_account_info(translate: {},
return '' return ''
following_domain, following_port = \ following_domain, following_port = \
get_domain_from_actor(following_actor) get_domain_from_actor(following_actor)
if not following_domain:
return ''
following_domain_full = \ following_domain_full = \
get_full_domain(following_domain, following_port) get_full_domain(following_domain, following_port)
if is_blocked(base_dir, nickname, domain, if is_blocked(base_dir, nickname, domain,
@ -242,6 +248,8 @@ def html_account_info(translate: {},
if not following_nickname: if not following_nickname:
return '' return ''
following_domain, following_port = get_domain_from_actor(actor) following_domain, following_port = get_domain_from_actor(actor)
if not following_domain:
return ''
following_domain_full = \ following_domain_full = \
get_full_domain(following_domain, following_port) get_full_domain(following_domain, following_port)
info_form += '<a href="' + actor + '" ' + \ info_form += '<a href="' + actor + '" ' + \
@ -263,6 +271,8 @@ def html_account_info(translate: {},
if not follower_nickname: if not follower_nickname:
return '' return ''
follower_domain, follower_port = get_domain_from_actor(actor) follower_domain, follower_port = get_domain_from_actor(actor)
if not follower_domain:
return ''
follower_domain_full = \ follower_domain_full = \
get_full_domain(follower_domain, follower_port) get_full_domain(follower_domain, follower_port)
info_form += '<a href="' + actor + '" ' + \ info_form += '<a href="' + actor + '" ' + \

View File

@ -336,14 +336,18 @@ def html_person_options(default_timeline: str,
other_accounts_html += ' ' other_accounts_html += ' '
ctr += 1 ctr += 1
alt_domain, _ = get_domain_from_actor(alt_actor) alt_domain, _ = get_domain_from_actor(alt_actor)
if not alt_domain:
continue
other_accounts_html += \ other_accounts_html += \
'<a href="' + alt_actor + '">' + alt_domain + '</a>' '<a href="' + alt_actor + '">' + alt_domain + '</a>'
elif isinstance(also_known_as, str): elif isinstance(also_known_as, str):
if also_known_as != options_actor: if also_known_as != options_actor:
ctr += 1 ctr += 1
alt_domain, _ = get_domain_from_actor(also_known_as) alt_domain, _ = get_domain_from_actor(also_known_as)
other_accounts_html += \ if alt_domain:
'<a href="' + also_known_as + '">' + alt_domain + '</a>' other_accounts_html += \
'<a href="' + also_known_as + '">' + \
alt_domain + '</a>'
other_accounts_html += '</p>\n' other_accounts_html += '</p>\n'
if ctr > 0: if ctr > 0:
options_str += other_accounts_html options_str += other_accounts_html

View File

@ -137,8 +137,8 @@ def _html_post_metadata_open_graph(domain: str, post_json_object: {},
if isinstance(obj_json['attributedTo'], str): if isinstance(obj_json['attributedTo'], str):
attrib = obj_json['attributedTo'] attrib = obj_json['attributedTo']
actor_nick = get_nickname_from_actor(attrib) actor_nick = get_nickname_from_actor(attrib)
if actor_nick: actor_domain, _ = get_domain_from_actor(attrib)
actor_domain, _ = get_domain_from_actor(attrib) if actor_nick and actor_domain:
actor_handle = actor_nick + '@' + actor_domain actor_handle = actor_nick + '@' + actor_domain
metadata += \ metadata += \
" <meta name=\"DC.creator\" " + \ " <meta name=\"DC.creator\" " + \
@ -512,9 +512,10 @@ def _get_reply_icon_html(base_dir: str, nickname: str, domain: str,
return reply_str return reply_str
block_domain, _ = \ block_domain, _ = \
get_domain_from_actor(post_json_object['object']['replyTo']) get_domain_from_actor(post_json_object['object']['replyTo'])
if not is_blocked(base_dir, nickname, domain, if block_domain:
block_nickname, block_domain, {}): if not is_blocked(base_dir, nickname, domain,
reply_to_link = post_json_object['object']['replyTo'] block_nickname, block_domain, {}):
reply_to_link = post_json_object['object']['replyTo']
if post_json_object['object'].get('attributedTo'): if post_json_object['object'].get('attributedTo'):
if isinstance(post_json_object['object']['attributedTo'], str): if isinstance(post_json_object['object']['attributedTo'], str):
@ -1306,7 +1307,7 @@ def _get_post_title_announce_html(base_dir: str,
if len(announce_display_name) < 2 or \ if len(announce_display_name) < 2 or \
display_name_is_emoji(announce_display_name): display_name_is_emoji(announce_display_name):
announce_display_name = None announce_display_name = None
if not announce_display_name: if not announce_display_name and announce_domain:
announce_display_name = announce_nickname + '@' + announce_domain announce_display_name = announce_nickname + '@' + announce_domain
_log_post_timing(enable_timing_log, post_start_time, '13.3') _log_post_timing(enable_timing_log, post_start_time, '13.3')
@ -1666,7 +1667,7 @@ def _get_footer_with_icons(show_icons: bool,
footer_str += delete_str + mute_str + edit_str + buy_str footer_str += delete_str + mute_str + edit_str + buy_str
if not is_news_post(post_json_object): if not is_news_post(post_json_object):
footer_str += ' ' footer_str += ' '
if content_license_url: if content_license_url and not is_reminder(post_json_object):
footer_str += _get_copyright_footer(content_license_url, footer_str += _get_copyright_footer(content_license_url,
translate) translate)
# show the date # show the date
@ -1798,11 +1799,17 @@ def _get_content_license(post_json_object: {}) -> str:
for item in post_json_object['object']['attachment']: for item in post_json_object['object']['attachment']:
if not item.get('name'): if not item.get('name'):
continue continue
if not item.get('value'): name_lower = item['name'].lower()
if 'license' not in name_lower and \
'copyright' not in name_lower and \
'licence' not in name_lower:
continue continue
if item['name'] != 'license': if item.get('value'):
value = item['value']
elif item.get('href'):
value = item['href']
else:
continue continue
value = item['value']
if '://' not in value: if '://' not in value:
value = license_link_from_name(value) value = license_link_from_name(value)
return value return value
@ -1986,6 +1993,8 @@ def individual_post_as_html(signing_priv_key_pem: str,
if not post_actor_nickname: if not post_actor_nickname:
return '' return ''
post_actor_domain, post_actor_port = get_domain_from_actor(post_actor) post_actor_domain, post_actor_port = get_domain_from_actor(post_actor)
if not post_actor_domain:
return ''
post_actor_domain_full = \ post_actor_domain_full = \
get_full_domain(post_actor_domain, post_actor_port) get_full_domain(post_actor_domain, post_actor_port)
post_actor_handle = post_actor_nickname + '@' + post_actor_domain_full post_actor_handle = post_actor_nickname + '@' + post_actor_domain_full
@ -2406,7 +2415,7 @@ def individual_post_as_html(signing_priv_key_pem: str,
footer_str = '' footer_str = ''
else: else:
footer_str = '<div class="' + container_class_icons + '">\n' footer_str = '<div class="' + container_class_icons + '">\n'
if content_license_url: if content_license_url and not is_reminder(post_json_object):
footer_str += _get_copyright_footer(content_license_url, footer_str += _get_copyright_footer(content_license_url,
translate) translate)
conv_link = '/users/' + nickname + '?convthread=' + \ conv_link = '/users/' + nickname + '?convthread=' + \
@ -2762,6 +2771,8 @@ def html_individual_post(recent_posts_cache: {}, max_recent_posts: int,
if not by_str_nickname: if not by_str_nickname:
return '' return ''
by_str_domain, by_str_port = get_domain_from_actor(by_str) by_str_domain, by_str_port = get_domain_from_actor(by_str)
if not by_str_domain:
return ''
by_str_domain = get_full_domain(by_str_domain, by_str_port) by_str_domain = get_full_domain(by_str_domain, by_str_port)
by_str_handle = by_str_nickname + '@' + by_str_domain by_str_handle = by_str_nickname + '@' + by_str_domain
if translate.get(by_text): if translate.get(by_text):

View File

@ -480,8 +480,8 @@ def _get_profile_header(base_dir: str, http_prefix: str, nickname: str,
if moved_to: if moved_to:
new_nickname = get_nickname_from_actor(moved_to) new_nickname = get_nickname_from_actor(moved_to)
new_domain, new_port = get_domain_from_actor(moved_to) new_domain, new_port = get_domain_from_actor(moved_to)
new_domain_full = get_full_domain(new_domain, new_port)
if new_nickname and new_domain: if new_nickname and new_domain:
new_domain_full = get_full_domain(new_domain, new_port)
html_str += \ html_str += \
' <p>' + translate['New account'] + ': ' + \ ' <p>' + translate['New account'] + ': ' + \
'<a href="' + moved_to + '">@' + \ '<a href="' + moved_to + '">@' + \
@ -500,15 +500,18 @@ def _get_profile_header(base_dir: str, http_prefix: str, nickname: str,
other_accounts_html += ' ' other_accounts_html += ' '
ctr += 1 ctr += 1
alt_domain, _ = get_domain_from_actor(alt_actor) alt_domain, _ = get_domain_from_actor(alt_actor)
other_accounts_html += \ if alt_domain:
'<a href="' + alt_actor + \ other_accounts_html += \
'" tabindex="1">' + alt_domain + '</a>' '<a href="' + alt_actor + \
'" tabindex="1">' + alt_domain + '</a>'
elif isinstance(also_known_as, str): elif isinstance(also_known_as, str):
if also_known_as != actor: if also_known_as != actor:
ctr += 1 ctr += 1
alt_domain, _ = get_domain_from_actor(also_known_as) alt_domain, _ = get_domain_from_actor(also_known_as)
other_accounts_html += \ if alt_domain:
'<a href="' + also_known_as + '">' + alt_domain + '</a>' other_accounts_html += \
'<a href="' + also_known_as + '">' + \
alt_domain + '</a>'
other_accounts_html += '</p>\n' other_accounts_html += '</p>\n'
if ctr > 0: if ctr > 0:
html_str += other_accounts_html html_str += other_accounts_html
@ -586,8 +589,8 @@ def _get_profile_header_after_search(nickname: str, default_timeline: str,
if moved_to: if moved_to:
new_nickname = get_nickname_from_actor(moved_to) new_nickname = get_nickname_from_actor(moved_to)
new_domain, new_port = get_domain_from_actor(moved_to) new_domain, new_port = get_domain_from_actor(moved_to)
new_domain_full = get_full_domain(new_domain, new_port)
if new_nickname and new_domain: if new_nickname and new_domain:
new_domain_full = get_full_domain(new_domain, new_port)
new_handle = new_nickname + '@' + new_domain_full new_handle = new_nickname + '@' + new_domain_full
html_str += ' <p>' + translate['New account'] + \ html_str += ' <p>' + translate['New account'] + \
': <a href="' + moved_to + '">@' + new_handle + '</a></p>\n' ': <a href="' + moved_to + '">@' + new_handle + '</a></p>\n'
@ -604,15 +607,18 @@ def _get_profile_header_after_search(nickname: str, default_timeline: str,
other_accounts_html += ' ' other_accounts_html += ' '
ctr += 1 ctr += 1
alt_domain, _ = get_domain_from_actor(alt_actor) alt_domain, _ = get_domain_from_actor(alt_actor)
other_accounts_html += \ if alt_domain:
'<a href="' + alt_actor + \ other_accounts_html += \
'" tabindex="1">' + alt_domain + '</a>' '<a href="' + alt_actor + \
'" tabindex="1">' + alt_domain + '</a>'
elif isinstance(also_known_as, str): elif isinstance(also_known_as, str):
if also_known_as != actor: if also_known_as != actor:
ctr += 1 ctr += 1
alt_domain, _ = get_domain_from_actor(also_known_as) alt_domain, _ = get_domain_from_actor(also_known_as)
other_accounts_html += \ if alt_domain:
'<a href="' + also_known_as + '">' + alt_domain + '</a>' other_accounts_html += \
'<a href="' + also_known_as + '">' + \
alt_domain + '</a>'
other_accounts_html += '</p>\n' other_accounts_html += '</p>\n'
if ctr > 0: if ctr > 0:
@ -2819,6 +2825,8 @@ def _individual_follow_as_html(signing_priv_key_pem: str,
if not follow_url_nickname: if not follow_url_nickname:
return '' return ''
follow_url_domain, follow_url_port = get_domain_from_actor(follow_url) follow_url_domain, follow_url_port = get_domain_from_actor(follow_url)
if not follow_url_domain:
return ''
follow_url_domain_full = \ follow_url_domain_full = \
get_full_domain(follow_url_domain, follow_url_port) get_full_domain(follow_url_domain, follow_url_port)
title_str = '@' + follow_url_nickname + '@' + follow_url_domain_full title_str = '@' + follow_url_nickname + '@' + follow_url_domain_full