mirror of https://gitlab.com/bashrc2/epicyon
Move daemon links column functions to their own module
parent
c5a94e7b33
commit
3e97d6c0f6
191
daemon_post.py
191
daemon_post.py
|
@ -13,11 +13,9 @@ import json
|
|||
import os
|
||||
import urllib.parse
|
||||
from socket import error as SocketError
|
||||
from utils import dangerous_markup
|
||||
from utils import binary_is_image
|
||||
from utils import get_image_extension_from_mime_type
|
||||
from utils import save_json
|
||||
from utils import is_editor
|
||||
from utils import get_config_param
|
||||
from utils import decoded_host
|
||||
from utils import get_new_post_endpoints
|
||||
|
@ -25,9 +23,7 @@ from utils import local_actor_url
|
|||
from utils import contains_invalid_chars
|
||||
from utils import remove_id_ending
|
||||
from utils import check_bad_path
|
||||
from utils import get_instance_url
|
||||
from utils import acct_dir
|
||||
from utils import get_nickname_from_actor
|
||||
from blocking import contains_military_domain
|
||||
from crawlers import blocked_user_agent
|
||||
from session import get_session_for_domain
|
||||
|
@ -37,7 +33,6 @@ from shares import update_shared_item_federation_token
|
|||
from inbox import inbox_message_has_params
|
||||
from inbox import inbox_permitted_message
|
||||
from httpsig import getheader_signature_input
|
||||
from content import extract_text_fields_in_post
|
||||
from httpcodes import http_200
|
||||
from httpcodes import http_404
|
||||
from httpcodes import http_400
|
||||
|
@ -67,6 +62,7 @@ from daemon_post_remove import receive_remove_post
|
|||
from daemon_post_question import receive_vote
|
||||
from daemon_post_theme import theme_designer_edit
|
||||
from daemon_post_hashtags import set_hashtag_category2
|
||||
from daemon_post_links import links_update
|
||||
|
||||
# maximum number of posts in a hashtag feed
|
||||
MAX_POSTS_IN_HASHTAG_FEED = 6
|
||||
|
@ -244,10 +240,10 @@ def daemon_http_post(self) -> None:
|
|||
return
|
||||
|
||||
if authorized and self.path.endswith('/linksdata'):
|
||||
_links_update(self, calling_domain, cookie, self.path,
|
||||
self.server.base_dir, self.server.debug,
|
||||
self.server.default_timeline,
|
||||
self.server.allow_local_network_access)
|
||||
links_update(self, calling_domain, cookie, self.path,
|
||||
self.server.base_dir, self.server.debug,
|
||||
self.server.default_timeline,
|
||||
self.server.allow_local_network_access)
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
|
@ -1184,180 +1180,3 @@ def _receive_image(self, length: int, path: str, base_dir: str,
|
|||
self.send_response(201)
|
||||
self.end_headers()
|
||||
self.server.postreq_busy = False
|
||||
|
||||
|
||||
def _links_update(self, calling_domain: str, cookie: str,
|
||||
path: str, base_dir: str, debug: bool,
|
||||
default_timeline: str,
|
||||
allow_local_network_access: bool) -> None:
|
||||
"""Updates the left links column of the timeline
|
||||
"""
|
||||
users_path = path.replace('/linksdata', '')
|
||||
users_path = users_path.replace('/editlinks', '')
|
||||
actor_str = \
|
||||
get_instance_url(calling_domain,
|
||||
self.server.http_prefix,
|
||||
self.server.domain_full,
|
||||
self.server.onion_domain,
|
||||
self.server.i2p_domain) + \
|
||||
users_path
|
||||
|
||||
boundary = None
|
||||
if ' boundary=' in self.headers['Content-type']:
|
||||
boundary = self.headers['Content-type'].split('boundary=')[1]
|
||||
if ';' in boundary:
|
||||
boundary = boundary.split(';')[0]
|
||||
|
||||
# get the nickname
|
||||
nickname = get_nickname_from_actor(actor_str)
|
||||
editor = None
|
||||
if nickname:
|
||||
editor = is_editor(base_dir, nickname)
|
||||
if not nickname or not editor:
|
||||
if not nickname:
|
||||
print('WARN: nickname not found in ' + actor_str)
|
||||
else:
|
||||
print('WARN: nickname is not a moderator' + actor_str)
|
||||
redirect_headers(self, actor_str, cookie, calling_domain)
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
if self.headers.get('Content-length'):
|
||||
length = int(self.headers['Content-length'])
|
||||
|
||||
# check that the POST isn't too large
|
||||
if length > self.server.max_post_length:
|
||||
print('Maximum links data length exceeded ' + str(length))
|
||||
redirect_headers(self, actor_str, cookie, calling_domain)
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
try:
|
||||
# read the bytes of the http form POST
|
||||
post_bytes = self.rfile.read(length)
|
||||
except SocketError as ex:
|
||||
if ex.errno == errno.ECONNRESET:
|
||||
print('EX: connection was reset while ' +
|
||||
'reading bytes from http form POST')
|
||||
else:
|
||||
print('EX: error while reading bytes ' +
|
||||
'from http form POST')
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
except ValueError as ex:
|
||||
print('EX: failed to read bytes for POST, ' + str(ex))
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
links_filename = base_dir + '/accounts/links.txt'
|
||||
about_filename = base_dir + '/accounts/about.md'
|
||||
tos_filename = base_dir + '/accounts/tos.md'
|
||||
specification_filename = base_dir + '/accounts/activitypub.md'
|
||||
|
||||
if not boundary:
|
||||
if b'--LYNX' in post_bytes:
|
||||
boundary = '--LYNX'
|
||||
|
||||
if boundary:
|
||||
# extract all of the text fields into a dict
|
||||
fields = \
|
||||
extract_text_fields_in_post(post_bytes, boundary, debug, None)
|
||||
|
||||
if fields.get('editedLinks'):
|
||||
links_str = fields['editedLinks']
|
||||
if fields.get('newColLink'):
|
||||
if links_str:
|
||||
if not links_str.endswith('\n'):
|
||||
links_str += '\n'
|
||||
links_str += fields['newColLink'] + '\n'
|
||||
try:
|
||||
with open(links_filename, 'w+',
|
||||
encoding='utf-8') as linksfile:
|
||||
linksfile.write(links_str)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to write ' +
|
||||
links_filename)
|
||||
else:
|
||||
if fields.get('newColLink'):
|
||||
# the text area is empty but there is a new link added
|
||||
links_str = fields['newColLink'] + '\n'
|
||||
try:
|
||||
with open(links_filename, 'w+',
|
||||
encoding='utf-8') as linksfile:
|
||||
linksfile.write(links_str)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to write ' +
|
||||
links_filename)
|
||||
else:
|
||||
if os.path.isfile(links_filename):
|
||||
try:
|
||||
os.remove(links_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
links_filename)
|
||||
|
||||
admin_nickname = \
|
||||
get_config_param(base_dir, 'admin')
|
||||
if nickname == admin_nickname:
|
||||
if fields.get('editedAbout'):
|
||||
about_str = fields['editedAbout']
|
||||
if not dangerous_markup(about_str,
|
||||
allow_local_network_access, []):
|
||||
try:
|
||||
with open(about_filename, 'w+',
|
||||
encoding='utf-8') as aboutfile:
|
||||
aboutfile.write(about_str)
|
||||
except OSError:
|
||||
print('EX: unable to write about ' +
|
||||
about_filename)
|
||||
else:
|
||||
if os.path.isfile(about_filename):
|
||||
try:
|
||||
os.remove(about_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
about_filename)
|
||||
|
||||
if fields.get('editedTOS'):
|
||||
tos_str = fields['editedTOS']
|
||||
if not dangerous_markup(tos_str,
|
||||
allow_local_network_access, []):
|
||||
try:
|
||||
with open(tos_filename, 'w+',
|
||||
encoding='utf-8') as tosfile:
|
||||
tosfile.write(tos_str)
|
||||
except OSError:
|
||||
print('EX: unable to write TOS ' + tos_filename)
|
||||
else:
|
||||
if os.path.isfile(tos_filename):
|
||||
try:
|
||||
os.remove(tos_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
tos_filename)
|
||||
|
||||
if fields.get('editedSpecification'):
|
||||
specification_str = fields['editedSpecification']
|
||||
try:
|
||||
with open(specification_filename, 'w+',
|
||||
encoding='utf-8') as specificationfile:
|
||||
specificationfile.write(specification_str)
|
||||
except OSError:
|
||||
print('EX: unable to write specification ' +
|
||||
specification_filename)
|
||||
else:
|
||||
if os.path.isfile(specification_filename):
|
||||
try:
|
||||
os.remove(specification_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
specification_filename)
|
||||
|
||||
# redirect back to the default timeline
|
||||
redirect_headers(self, actor_str + '/' + default_timeline,
|
||||
cookie, calling_domain)
|
||||
self.server.postreq_busy = False
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
__filename__ = "daemon_post_links.py"
|
||||
__author__ = "Bob Mottram"
|
||||
__license__ = "AGPL3+"
|
||||
__version__ = "1.5.0"
|
||||
__maintainer__ = "Bob Mottram"
|
||||
__email__ = "bob@libreserver.org"
|
||||
__status__ = "Production"
|
||||
__module_group__ = "Core"
|
||||
|
||||
import os
|
||||
import errno
|
||||
from socket import error as SocketError
|
||||
from utils import dangerous_markup
|
||||
from utils import get_instance_url
|
||||
from utils import get_nickname_from_actor
|
||||
from utils import is_editor
|
||||
from utils import get_config_param
|
||||
from httpheaders import redirect_headers
|
||||
from content import extract_text_fields_in_post
|
||||
|
||||
|
||||
def links_update(self, calling_domain: str, cookie: str,
|
||||
path: str, base_dir: str, debug: bool,
|
||||
default_timeline: str,
|
||||
allow_local_network_access: bool) -> None:
|
||||
"""Updates the left links column of the timeline
|
||||
"""
|
||||
users_path = path.replace('/linksdata', '')
|
||||
users_path = users_path.replace('/editlinks', '')
|
||||
actor_str = \
|
||||
get_instance_url(calling_domain,
|
||||
self.server.http_prefix,
|
||||
self.server.domain_full,
|
||||
self.server.onion_domain,
|
||||
self.server.i2p_domain) + \
|
||||
users_path
|
||||
|
||||
boundary = None
|
||||
if ' boundary=' in self.headers['Content-type']:
|
||||
boundary = self.headers['Content-type'].split('boundary=')[1]
|
||||
if ';' in boundary:
|
||||
boundary = boundary.split(';')[0]
|
||||
|
||||
# get the nickname
|
||||
nickname = get_nickname_from_actor(actor_str)
|
||||
editor = None
|
||||
if nickname:
|
||||
editor = is_editor(base_dir, nickname)
|
||||
if not nickname or not editor:
|
||||
if not nickname:
|
||||
print('WARN: nickname not found in ' + actor_str)
|
||||
else:
|
||||
print('WARN: nickname is not a moderator' + actor_str)
|
||||
redirect_headers(self, actor_str, cookie, calling_domain)
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
if self.headers.get('Content-length'):
|
||||
length = int(self.headers['Content-length'])
|
||||
|
||||
# check that the POST isn't too large
|
||||
if length > self.server.max_post_length:
|
||||
print('Maximum links data length exceeded ' + str(length))
|
||||
redirect_headers(self, actor_str, cookie, calling_domain)
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
try:
|
||||
# read the bytes of the http form POST
|
||||
post_bytes = self.rfile.read(length)
|
||||
except SocketError as ex:
|
||||
if ex.errno == errno.ECONNRESET:
|
||||
print('EX: connection was reset while ' +
|
||||
'reading bytes from http form POST')
|
||||
else:
|
||||
print('EX: error while reading bytes ' +
|
||||
'from http form POST')
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
except ValueError as ex:
|
||||
print('EX: failed to read bytes for POST, ' + str(ex))
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
self.server.postreq_busy = False
|
||||
return
|
||||
|
||||
links_filename = base_dir + '/accounts/links.txt'
|
||||
about_filename = base_dir + '/accounts/about.md'
|
||||
tos_filename = base_dir + '/accounts/tos.md'
|
||||
specification_filename = base_dir + '/accounts/activitypub.md'
|
||||
|
||||
if not boundary:
|
||||
if b'--LYNX' in post_bytes:
|
||||
boundary = '--LYNX'
|
||||
|
||||
if boundary:
|
||||
# extract all of the text fields into a dict
|
||||
fields = \
|
||||
extract_text_fields_in_post(post_bytes, boundary, debug, None)
|
||||
|
||||
if fields.get('editedLinks'):
|
||||
links_str = fields['editedLinks']
|
||||
if fields.get('newColLink'):
|
||||
if links_str:
|
||||
if not links_str.endswith('\n'):
|
||||
links_str += '\n'
|
||||
links_str += fields['newColLink'] + '\n'
|
||||
try:
|
||||
with open(links_filename, 'w+',
|
||||
encoding='utf-8') as linksfile:
|
||||
linksfile.write(links_str)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to write ' +
|
||||
links_filename)
|
||||
else:
|
||||
if fields.get('newColLink'):
|
||||
# the text area is empty but there is a new link added
|
||||
links_str = fields['newColLink'] + '\n'
|
||||
try:
|
||||
with open(links_filename, 'w+',
|
||||
encoding='utf-8') as linksfile:
|
||||
linksfile.write(links_str)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to write ' +
|
||||
links_filename)
|
||||
else:
|
||||
if os.path.isfile(links_filename):
|
||||
try:
|
||||
os.remove(links_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
links_filename)
|
||||
|
||||
admin_nickname = \
|
||||
get_config_param(base_dir, 'admin')
|
||||
if nickname == admin_nickname:
|
||||
if fields.get('editedAbout'):
|
||||
about_str = fields['editedAbout']
|
||||
if not dangerous_markup(about_str,
|
||||
allow_local_network_access, []):
|
||||
try:
|
||||
with open(about_filename, 'w+',
|
||||
encoding='utf-8') as aboutfile:
|
||||
aboutfile.write(about_str)
|
||||
except OSError:
|
||||
print('EX: unable to write about ' +
|
||||
about_filename)
|
||||
else:
|
||||
if os.path.isfile(about_filename):
|
||||
try:
|
||||
os.remove(about_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
about_filename)
|
||||
|
||||
if fields.get('editedTOS'):
|
||||
tos_str = fields['editedTOS']
|
||||
if not dangerous_markup(tos_str,
|
||||
allow_local_network_access, []):
|
||||
try:
|
||||
with open(tos_filename, 'w+',
|
||||
encoding='utf-8') as tosfile:
|
||||
tosfile.write(tos_str)
|
||||
except OSError:
|
||||
print('EX: unable to write TOS ' + tos_filename)
|
||||
else:
|
||||
if os.path.isfile(tos_filename):
|
||||
try:
|
||||
os.remove(tos_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
tos_filename)
|
||||
|
||||
if fields.get('editedSpecification'):
|
||||
specification_str = fields['editedSpecification']
|
||||
try:
|
||||
with open(specification_filename, 'w+',
|
||||
encoding='utf-8') as specificationfile:
|
||||
specificationfile.write(specification_str)
|
||||
except OSError:
|
||||
print('EX: unable to write specification ' +
|
||||
specification_filename)
|
||||
else:
|
||||
if os.path.isfile(specification_filename):
|
||||
try:
|
||||
os.remove(specification_filename)
|
||||
except OSError:
|
||||
print('EX: _links_update unable to delete ' +
|
||||
specification_filename)
|
||||
|
||||
# redirect back to the default timeline
|
||||
redirect_headers(self, actor_str + '/' + default_timeline,
|
||||
cookie, calling_domain)
|
||||
self.server.postreq_busy = False
|
Loading…
Reference in New Issue