merge-requests/30/head
Bob Mottram 2023-01-08 23:40:41 +00:00
commit 57f9a61a78
13 changed files with 409 additions and 308 deletions

View File

@ -1381,15 +1381,15 @@ def add_cw_from_lists(post_json_object: {}, cw_lists: {}, translate: {},
"""
if not lists_enabled:
return
if not post_json_object['object'].get('content'):
if not post_json_object['object'].get('contentMap'):
if 'content' not in post_json_object['object']:
if 'contentMap' not in post_json_object['object']:
return
cw_text = ''
if post_json_object['object'].get('summary'):
cw_text = post_json_object['object']['summary']
content = None
if post_json_object['object'].get('contentMap'):
if 'contentMap' in post_json_object['object']:
if post_json_object['object']['contentMap'].get(system_language):
content = \
post_json_object['object']['contentMap'][system_language]

View File

@ -2006,8 +2006,8 @@ def create_edits_html(edits_json: {}, post_json_object: {},
return ''
if not has_object_dict(post_json_object):
return ''
if not post_json_object['object'].get('content'):
if not post_json_object['object'].get('contentMap'):
if 'content' not in post_json_object['object']:
if 'contentMap' not in post_json_object['object']:
return ''
edit_dates_list = []
for modified, _ in edits_json.items():
@ -2015,14 +2015,14 @@ def create_edits_html(edits_json: {}, post_json_object: {},
edit_dates_list.sort(reverse=True)
edits_str = ''
content = None
if post_json_object['object'].get('contentMap'):
if 'contentMap' in post_json_object['object']:
if post_json_object['object']['contentMap'].get(system_language):
content = \
post_json_object['object']['contentMap'][system_language]
if not content:
if post_json_object['object'].get('content'):
if content is None:
if 'content' in post_json_object['object']:
content = post_json_object['object']['content']
if not content:
if content is None:
return ''
content = remove_html(content)
for modified in edit_dates_list:
@ -2030,17 +2030,17 @@ def create_edits_html(edits_json: {}, post_json_object: {},
if not has_object_dict(prev_json):
continue
prev_content = None
if not prev_json['object'].get('content'):
if not prev_json['object'].get('contentMap'):
if 'content' not in prev_json['object']:
if 'contentMap' not in prev_json['object']:
continue
if prev_json['object'].get('contentMap'):
if 'contentMap' in prev_json['object']:
if prev_json['object']['contentMap'].get(system_language):
prev_content = \
prev_json['object']['contentMap'][system_language]
if not prev_content:
if prev_json['object'].get('content'):
if prev_content is None:
if 'content' in prev_json['object']:
prev_content = prev_json['object']['content']
if not prev_content:
if prev_content is None:
continue
prev_content = remove_html(prev_content)
if content == prev_content:

View File

@ -2034,6 +2034,37 @@ class PubServer(BaseHTTPRequestHandler):
self._400()
self.server.postreq_busy = False
return 3
# if this is a local only post, is it really local?
if 'localOnly' in message_json['object'] and \
message_json['object'].get('to') and \
message_json['object'].get('attributedTo'):
if message_json['object']['localOnly'] is True:
# check that the to addresses are local
if isinstance(message_json['object']['to'], list):
for to_actor in message_json['object']['to']:
to_domain, to_port = \
get_domain_from_actor(to_actor)
to_domain_full = \
get_full_domain(to_domain, to_port)
if self.server.domain_full != to_domain_full:
print("REJECT: inbox " +
"local only post isn't local " +
str(message_json))
self._400()
self.server.postreq_busy = False
return 3
# check that the sender is local
local_actor = message_json['object']['attributedTo']
local_domain, local_port = \
get_domain_from_actor(local_actor)
local_domain_full = \
get_full_domain(local_domain, local_port)
if self.server.domain_full != local_domain_full:
print("REJECT: inbox local only post isn't local " +
str(message_json))
self._400()
self.server.postreq_busy = False
return 3
# actor should look like a url
if debug:
@ -4851,6 +4882,36 @@ class PubServer(BaseHTTPRequestHandler):
curr_session, proxy_type: str) -> None:
"""Receive a vote via POST
"""
first_post_id = ''
if '?firstpost=' in path:
first_post_id = path.split('?firstpost=')[1]
path = path.split('?firstpost=')[0]
if ';firstpost=' in path:
first_post_id = path.split(';firstpost=')[1]
path = path.split(';firstpost=')[0]
if first_post_id:
if '?' in first_post_id:
first_post_id = first_post_id.split('?')[0]
if ';' in first_post_id:
first_post_id = first_post_id.split(';')[0]
first_post_id = first_post_id.replace('/', '--')
first_post_id = ';firstpost=' + first_post_id.replace('#', '--')
last_post_id = ''
if '?lastpost=' in path:
last_post_id = path.split('?lastpost=')[1]
path = path.split('?lastpost=')[0]
if ';lastpost=' in path:
last_post_id = path.split(';lastpost=')[1]
path = path.split(';lastpost=')[0]
if last_post_id:
if '?' in last_post_id:
last_post_id = last_post_id.split('?')[0]
if ';' in last_post_id:
last_post_id = last_post_id.split(';')[0]
last_post_id = last_post_id.replace('/', '--')
last_post_id = ';lastpost=' + last_post_id.replace('#', '--')
page_number = 1
if '?page=' in path:
page_number_str = path.split('?page=')[1]
@ -4860,7 +4921,6 @@ class PubServer(BaseHTTPRequestHandler):
page_number_str = "1"
if page_number_str.isdigit():
page_number = int(page_number_str)
path = path.split('?page=')[0]
# the actor who votes
users_path = path.replace('/question', '')
@ -4926,7 +4986,7 @@ class PubServer(BaseHTTPRequestHandler):
actor = 'http://' + i2p_domain + users_path
actor_path_str = \
actor + '/' + self.server.default_timeline + \
'?page=' + str(page_number)
'?page=' + str(page_number) + first_post_id + last_post_id
self._redirect_headers(actor_path_str, cookie,
calling_domain)
self.server.postreq_busy = False
@ -21998,7 +22058,9 @@ class PubServer(BaseHTTPRequestHandler):
else:
# a vote/question/poll is posted
if self.path.endswith('/question') or \
'/question?page=' in self.path:
'/question?page=' in self.path or \
'/question?firstpost=' in self.path or \
'/question?lastpost=' in self.path:
self._receive_vote(calling_domain, cookie,
self.path,
self.server.http_prefix,

File diff suppressed because one or more lines are too long

View File

@ -772,10 +772,10 @@ a:focus {
}
.container img.attachment {
max-width: 140%;
width: 125%;
max-width: 145%;
margin-left: -2%;
margin-right: 2%;
width: 125%;
padding-bottom: 3%;
}

View File

@ -341,7 +341,7 @@ def store_hash_tags(base_dir: str, nickname: str, domain: str,
# get geolocations from content
map_links = []
published = None
if post_json_object['object'].get('content'):
if 'content' in post_json_object['object']:
published = post_json_object['object']['published']
post_content = post_json_object['object']['content']
map_links += get_map_links_from_post_content(post_content)
@ -898,7 +898,8 @@ def _inbox_post_recipients(base_dir: str, post_json_object: {},
else:
if debug and post_json_object.get('object'):
if isinstance(post_json_object['object'], str):
if '/statuses/' in post_json_object['object']:
if '/statuses/' in post_json_object['object'] or \
'/objects/' in post_json_object['object']:
print('DEBUG: inbox item is a link to a post')
else:
if '/users/' in post_json_object['object']:
@ -1294,9 +1295,9 @@ def receive_edit_to_post(recent_posts_cache: {}, message_json: {},
return False
if not has_object_dict(post_json_object):
return False
if not post_json_object['object'].get('content'):
if 'content' not in post_json_object['object']:
return False
if not message_json['object'].get('content'):
if 'content' not in message_json['object']:
return False
# does the actor match?
if post_json_object['actor'] != message_json['actor']:
@ -1775,7 +1776,7 @@ def _receive_reaction(recent_posts_cache: {},
return False
if not has_object_string(message_json, debug):
return False
if not message_json.get('content'):
if 'content' not in message_json:
if debug:
print('DEBUG: ' + message_json['type'] + ' has no "content"')
return False
@ -1938,7 +1939,7 @@ def _receive_zot_reaction(recent_posts_cache: {},
return False
if message_json['object']['type'] != 'Note':
return False
if not message_json['object'].get('content'):
if 'content' not in message_json['object']:
if debug:
print('DEBUG: ' + message_json['object']['type'] +
' has no "content"')
@ -2118,7 +2119,7 @@ def _receive_undo_reaction(recent_posts_cache: {},
return False
if not has_object_string_object(message_json, debug):
return False
if not message_json['object'].get('content'):
if 'content' not in message_json['object']:
if debug:
print('DEBUG: ' + message_json['type'] + ' has no "content"')
return False
@ -2774,6 +2775,8 @@ def _receive_announce(recent_posts_cache: {},
if has_users_path(lookup_actor):
if '/statuses/' in lookup_actor:
lookup_actor = lookup_actor.split('/statuses/')[0]
elif '/objects/' in lookup_actor:
lookup_actor = lookup_actor.split('/objects/')[0]
if is_recent_post(post_json_object, 3):
if not os.path.isfile(post_filename + '.tts'):
@ -3009,7 +3012,7 @@ def _valid_post_content(base_dir: str, nickname: str, domain: str,
"""
if not has_object_dict(message_json):
return True
if not message_json['object'].get('content'):
if 'content' not in message_json['object']:
return True
if not message_json['object'].get('published'):

View File

@ -207,7 +207,7 @@ def _capitalize_hashtag(content: str, message_json: {},
if '#' + original_tag not in content:
return
content = content.replace('#' + original_tag, '#' + capitalized_tag)
if message_json['object'].get('contentMap'):
if 'contentMap' in message_json['object']:
if message_json['object']['contentMap'].get(system_language):
message_json['object']['contentMap'][system_language] = content
message_json['object']['contentMap'][system_language] = content
@ -265,6 +265,29 @@ def post_message_to_outbox(session, translate: {},
# check that the outgoing post doesn't contain any markup
# which can be used to implement exploits
if has_object_dict(message_json):
# if this is a local only post, is it really local?
if 'localOnly' in message_json['object'] and \
message_json['object'].get('to') and \
message_json['object'].get('attributedTo'):
if message_json['object']['localOnly'] is True:
# check that the to addresses are local
if isinstance(message_json['object']['to'], list):
for to_actor in message_json['object']['to']:
to_domain, to_port = get_domain_from_actor(to_actor)
to_domain_full = get_full_domain(to_domain, to_port)
if domain_full != to_domain_full:
print("REJECT: local only post isn't local " +
str(message_json))
return False
# check that the sender is local
local_actor = message_json['object']['attributedTo']
local_domain, local_port = get_domain_from_actor(local_actor)
local_domain_full = get_full_domain(local_domain, local_port)
if domain_full != local_domain_full:
print("REJECT: local only post isn't local " +
str(message_json))
return False
if is_quote_toot(message_json, ''):
print('REJECT: POST quote toot ' + str(message_json))
return False

View File

@ -1199,7 +1199,8 @@ def can_remove_post(base_dir: str,
domain: str, port: int, post_id: str) -> bool:
"""Returns true if the given post can be removed
"""
if '/statuses/' not in post_id:
if '/statuses/' not in post_id and \
'/objects/' not in post_id:
return False
domain_full = get_full_domain(domain, port)

View File

@ -5240,6 +5240,9 @@ def download_announce(session, base_dir: str, http_prefix: str,
base_dir, nickname, domain, post_id,
recent_posts_cache)
return None
announced_actor = announced_json['id']
if announced_json.get('attributedTo'):
announced_actor = announced_json['attributedTo']
if not announced_json.get('type'):
print('WARN: announced post does not have a type ' +
str(announced_json))
@ -5254,14 +5257,15 @@ def download_announce(session, base_dir: str, http_prefix: str,
announced_json, blocked_cache)
if converted_json:
announced_json = converted_json
if '/statuses/' not in announced_json['id']:
if '/statuses/' not in announced_json['id'] and \
'/objects/' not in announced_json['id']:
print('WARN: announced post id does not contain /statuses/ ' +
str(announced_json))
'or /objects/' + str(announced_json))
_reject_announce(announce_filename,
base_dir, nickname, domain, post_id,
recent_posts_cache)
return None
if not has_users_path(announced_json['id']):
if not has_users_path(announced_actor):
print('WARN: announced post id does not contain /users/ ' +
str(announced_json))
_reject_announce(announce_filename,
@ -5278,7 +5282,7 @@ def download_announce(session, base_dir: str, http_prefix: str,
base_dir, nickname, domain, post_id,
recent_posts_cache)
return None
if not announced_json.get('content'):
if 'content' not in announced_json:
print('WARN: announced post does not have content ' +
str(announced_json))
_reject_announce(announce_filename,
@ -5311,7 +5315,7 @@ def download_announce(session, base_dir: str, http_prefix: str,
# Check the content of the announce
content_str = announced_json['content']
using_content_map = False
if announced_json.get('contentMap'):
if 'contentMap' in announced_json:
if announced_json['contentMap'].get(system_language):
content_str = announced_json['contentMap'][system_language]
using_content_map = True
@ -5875,7 +5879,7 @@ def edited_post_filename(base_dir: str, nickname: str, domain: str,
return '', None
if not post_json_object['object'].get('id'):
return '', None
if not post_json_object['object'].get('content'):
if 'content' not in post_json_object['object']:
return '', None
if not post_json_object['object'].get('attributedTo'):
return '', None
@ -5919,7 +5923,7 @@ def edited_post_filename(base_dir: str, nickname: str, domain: str,
return '', None
if not lastpost_json['object'].get('id'):
return '', None
if not lastpost_json['object'].get('content'):
if 'content' not in lastpost_json['object']:
return '', None
if not lastpost_json['object'].get('attributedTo'):
return '', None
@ -5933,12 +5937,12 @@ def edited_post_filename(base_dir: str, nickname: str, domain: str,
if debug:
print(post_id + ' might be an edit of ' + lastpost_id)
lastpost_content = lastpost_json['object']['content']
if lastpost_json['object'].get('contentMap'):
if 'contentMap' in lastpost_json['object']:
if lastpost_json['object']['contentMap'].get(system_language):
lastpost_content = \
lastpost_json['object']['contentMap'][system_language]
content = post_json_object['object']['content']
if post_json_object['object'].get('contentMap'):
if 'contentMap' in post_json_object['object']:
if post_json_object['object']['contentMap'].get(system_language):
content = \
post_json_object['object']['contentMap'][system_language]

View File

@ -287,7 +287,7 @@ def get_base_content_from_post(post_json_object: {},
this_post_json = post_json_object
if has_object_dict(post_json_object):
this_post_json = post_json_object['object']
if not this_post_json.get('content'):
if 'content' not in this_post_json:
return ''
return this_post_json['content']
@ -2571,7 +2571,7 @@ def is_blog_post(post_json_object: {}) -> bool:
return False
if not has_object_string_type(post_json_object, False):
return False
if not post_json_object['object'].get('content'):
if 'content' not in post_json_object['object']:
return False
if post_json_object['object']['type'] != 'Article':
return False
@ -4164,11 +4164,12 @@ def save_reverse_timeline(base_dir: str, reverse_sequence: []) -> []:
def is_quote_toot(post_json_object: str, content: str) -> bool:
"""Returns true if the given post is a quote toot
"""
# Pleroma implementation
# Pleroma/Misskey implementations
if post_json_object['object'].get('quoteUri') or \
post_json_object['object'].get('quoteUrl'):
post_json_object['object'].get('quoteUrl') or \
post_json_object['object'].get('_misskey_quote'):
return True
# More correct ActivityPub implementation
# More correct ActivityPub implementation - adding a Link tag
if post_json_object['object'].get('tag'):
if isinstance(post_json_object['object']['tag'], list):
for item in post_json_object['object']['tag']:
@ -4187,6 +4188,7 @@ def is_quote_toot(post_json_object: str, content: str) -> bool:
if 'json' not in item['mediaType']:
continue
return True
# Twitter-style indicator
if content:
if 'QT: ' in content:
return True

View File

@ -91,7 +91,7 @@ def convert_video_to_note(base_dir: str, nickname: str, domain: str,
return None
content += '<p>' + post_json_object['license']['name'] + '</p>'
post_content = post_json_object['content']
if post_json_object.get('contentMap'):
if 'contentMap' in post_json_object:
if post_json_object['contentMap'].get(system_language):
post_content = post_json_object['contentMap'][system_language]
content += post_content

View File

@ -158,9 +158,9 @@ def _html_post_metadata_open_graph(domain: str, post_json_object: {},
" <meta content=\"" + obj_json['published'] + \
"\" property=\"og:published_time\" />\n"
if not obj_json.get('attachment') or obj_json.get('sensitive'):
if obj_json.get('content') and not obj_json.get('sensitive'):
if 'content' in obj_json and not obj_json.get('sensitive'):
obj_content = obj_json['content']
if obj_json.get('contentMap'):
if 'contentMap' in obj_json:
if obj_json['contentMap'].get(system_language):
obj_content = obj_json['contentMap'][system_language]
description = remove_html(obj_content)
@ -190,9 +190,9 @@ def _html_post_metadata_open_graph(domain: str, post_json_object: {},
elif attach_json['mediaType'].startswith('audio/'):
description = 'Attached: 1 audio'
if description:
if obj_json.get('content') and not obj_json.get('sensitive'):
if 'content' in obj_json and not obj_json.get('sensitive'):
obj_content = obj_json['content']
if obj_json.get('contentMap'):
if 'contentMap' in obj_json:
if obj_json['contentMap'].get(system_language):
obj_content = obj_json['contentMap'][system_language]
description += '\n\n' + remove_html(obj_content)

View File

@ -1333,7 +1333,7 @@ def rss_hashtag_search(nickname: str, domain: str, port: int,
break
continue
# add to feed
if post_json_object['object'].get('content') and \
if 'content' in post_json_object['object'] and \
post_json_object['object'].get('attributedTo') and \
post_json_object['object'].get('published'):
published = post_json_object['object']['published']