forked from MarseyWorld/MarseyWorld
crgd is a king
parent
3c691595e5
commit
386db76c10
|
@ -472,17 +472,17 @@ class Submission(Base):
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def is_video(self):
|
def is_video(self):
|
||||||
return self.url and any((self.url.lower().endswith(x) for x in ('.mp4','.webm','.mov'))) and embed_fullmatch_regex.fullmatch(self.url)
|
return self.url and any((self.url.lower().endswith(x) for x in ('.mp4','.webm','.mov'))) and is_safe_url(self.url)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def is_audio(self):
|
def is_audio(self):
|
||||||
return self.url and any((self.url.lower().endswith(x) for x in ('.mp3','.wav','.ogg','.aac','.m4a','.flac'))) and embed_fullmatch_regex.fullmatch(self.url)
|
return self.url and any((self.url.lower().endswith(x) for x in ('.mp3','.wav','.ogg','.aac','.m4a','.flac'))) and is_safe_url(self.url)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def is_image(self):
|
def is_image(self):
|
||||||
if self.url and (self.url.lower().endswith('.webp') or self.url.lower().endswith('.jpg') or self.url.lower().endswith('.png') or self.url.lower().endswith('.gif') or self.url.lower().endswith('.jpeg') or self.url.lower().endswith('?maxwidth=9999') or self.url.lower().endswith('&fidelity=high')) and (self.url.startswith('/') or self.url.startswith(f'{SITE_FULL}/') or embed_fullmatch_regex.fullmatch(self.url)):
|
if self.url and (self.url.lower().endswith('.webp') or self.url.lower().endswith('.jpg') or self.url.lower().endswith('.png') or self.url.lower().endswith('.gif') or self.url.lower().endswith('.jpeg') or self.url.lower().endswith('?maxwidth=9999') or self.url.lower().endswith('&fidelity=high')) and is_safe_url(self.url):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ from files.__main__ import db_session
|
||||||
from files.classes.sub import Sub
|
from files.classes.sub import Sub
|
||||||
from files.classes.marsey import Marsey
|
from files.classes.marsey import Marsey
|
||||||
from flask import request
|
from flask import request
|
||||||
|
import tldextract
|
||||||
|
|
||||||
SITE = environ.get("DOMAIN", '').strip()
|
SITE = environ.get("DOMAIN", '').strip()
|
||||||
SITE_NAME = environ.get("SITE_NAME", '').strip()
|
SITE_NAME = environ.get("SITE_NAME", '').strip()
|
||||||
|
@ -875,7 +876,7 @@ proxies = {"http":"http://127.0.0.1:18080","https":"http://127.0.0.1:18080"}
|
||||||
|
|
||||||
blackjack = environ.get("BLACKJACK", "").strip()
|
blackjack = environ.get("BLACKJACK", "").strip()
|
||||||
|
|
||||||
approved_embed_hosts = [
|
approved_embed_hosts = {
|
||||||
SITE,
|
SITE,
|
||||||
'rdrama.net',
|
'rdrama.net',
|
||||||
'pcmemes.net',
|
'pcmemes.net',
|
||||||
|
@ -935,14 +936,17 @@ approved_embed_hosts = [
|
||||||
'typekit.net',
|
'typekit.net',
|
||||||
'postimg.cc',
|
'postimg.cc',
|
||||||
'archive.org'
|
'archive.org'
|
||||||
]
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def is_safe_url(url):
|
||||||
|
return '\\' not in url and (url.startswith('/') or tldextract.extract(url).registered_domain in approved_embed_hosts)
|
||||||
|
|
||||||
|
|
||||||
hosts = "|".join(approved_embed_hosts).replace('.','\.')
|
hosts = "|".join(approved_embed_hosts).replace('.','\.')
|
||||||
|
|
||||||
image_check_regex = re.compile(f'!\[\]\(((?!(https:\/\/([a-z0-9-]+\.)*({hosts})\/|\/)).*?)\)', flags=re.A)
|
image_check_regex = re.compile(f'!\[\]\(((?!(https:\/\/([a-z0-9-]+\.)*({hosts})\/|\/)).*?)\)', flags=re.A)
|
||||||
|
|
||||||
embed_fullmatch_regex = re.compile(f'https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*', flags=re.A)
|
|
||||||
|
|
||||||
video_sub_regex = re.compile(f'(<p>[^<]*)(https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*?\.(mp4|webm|mov))', flags=re.A)
|
video_sub_regex = re.compile(f'(<p>[^<]*)(https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*?\.(mp4|webm|mov))', flags=re.A)
|
||||||
audio_sub_regex = re.compile(f'(<p>[^<]*)(https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*?\.(mp3|wav|ogg|aac|m4a|flac))', flags=re.A)
|
audio_sub_regex = re.compile(f'(<p>[^<]*)(https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*?\.(mp3|wav|ogg|aac|m4a|flac))', flags=re.A)
|
||||||
|
|
||||||
|
|
|
@ -53,16 +53,13 @@ def allowed_attributes(tag, name, value):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if tag == 'a':
|
if tag == 'a':
|
||||||
if name == 'href': return True
|
if name == 'href' and '\\' not in value: return True
|
||||||
if name == 'rel' and value == 'nofollow noopener noreferrer': return True
|
if name == 'rel' and value == 'nofollow noopener noreferrer': return True
|
||||||
if name == 'target' and value == '_blank': return True
|
if name == 'target' and value == '_blank': return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if tag == 'img':
|
if tag == 'img':
|
||||||
if name in ['src','data-src']:
|
if name in ['src','data-src']: return is_safe_url(value)
|
||||||
if value.startswith('/') or value.startswith(f'{SITE_FULL}/') or embed_fullmatch_regex.fullmatch(value): return True
|
|
||||||
else: return False
|
|
||||||
|
|
||||||
if name == 'loading' and value == 'lazy': return True
|
if name == 'loading' and value == 'lazy': return True
|
||||||
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
||||||
if name in ['g','b'] and not value: return True
|
if name in ['g','b'] and not value: return True
|
||||||
|
@ -81,13 +78,12 @@ def allowed_attributes(tag, name, value):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if tag == 'source':
|
if tag == 'source':
|
||||||
if name == 'src' and embed_fullmatch_regex.fullmatch(value): return True
|
if name == 'src': return is_safe_url(value)
|
||||||
return False
|
|
||||||
|
|
||||||
if tag == 'audio':
|
if tag == 'audio':
|
||||||
|
if name == 'src': return is_safe_url(value)
|
||||||
if name == 'controls' and value == '': return True
|
if name == 'controls' and value == '': return True
|
||||||
if name == 'preload' and value == 'none': return True
|
if name == 'preload' and value == 'none': return True
|
||||||
if name == 'src' and embed_fullmatch_regex.fullmatch(value): return True
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if tag == 'p':
|
if tag == 'p':
|
||||||
|
@ -349,7 +345,7 @@ def sanitize(sanitized, alert=False, comment=False, edit=False):
|
||||||
def allowed_attributes_emojis(tag, name, value):
|
def allowed_attributes_emojis(tag, name, value):
|
||||||
|
|
||||||
if tag == 'img':
|
if tag == 'img':
|
||||||
if name == 'src' and value.startswith('/'): return True
|
if name == 'src' and value.startswith('/') and '\\' not in value: return True
|
||||||
if name == 'loading' and value == 'lazy': return True
|
if name == 'loading' and value == 'lazy': return True
|
||||||
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
if name == 'data-bs-toggle' and value == 'tooltip': return True
|
||||||
if name == 'g' and not value: return True
|
if name == 'g' and not value: return True
|
||||||
|
|
|
@ -660,6 +660,8 @@ def badge_grant_post(v):
|
||||||
if desc: new_badge.description = desc
|
if desc: new_badge.description = desc
|
||||||
|
|
||||||
url = request.values.get("url")
|
url = request.values.get("url")
|
||||||
|
if '\\' in url: abort(400)
|
||||||
|
|
||||||
if url: new_badge.url = url
|
if url: new_badge.url = url
|
||||||
|
|
||||||
g.db.add(new_badge)
|
g.db.add(new_badge)
|
||||||
|
|
|
@ -72,5 +72,5 @@ def allow_nsfw():
|
||||||
redir = request.values.get("redir")
|
redir = request.values.get("redir")
|
||||||
if redir:
|
if redir:
|
||||||
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
||||||
if redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
|
if redir.startswith('/') and '\\' not in redir: return redirect(f'{SITE_FULL}{redir}')
|
||||||
return redirect('/')
|
return redirect('/')
|
|
@ -11,11 +11,11 @@ def login_get(v):
|
||||||
redir = request.values.get("redirect")
|
redir = request.values.get("redirect")
|
||||||
if redir:
|
if redir:
|
||||||
redir = redir.replace("/logged_out", "").strip()
|
redir = redir.replace("/logged_out", "").strip()
|
||||||
if not redir.startswith(f'{SITE_FULL}/') and not redir.startswith('/'): redir = None
|
if not redir.startswith(f'{SITE_FULL}/') and not (redir.startswith('/') and '\\' not in redir): redir = None
|
||||||
|
|
||||||
if v and redir:
|
if v and redir:
|
||||||
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
||||||
elif redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
|
elif redir.startswith('/') and '\\' not in redir: return redirect(f'{SITE_FULL}{redir}')
|
||||||
|
|
||||||
return render_template("login.html", failed=False, redirect=redir)
|
return render_template("login.html", failed=False, redirect=redir)
|
||||||
|
|
||||||
|
@ -150,11 +150,11 @@ def login_post():
|
||||||
redir = request.values.get("redirect")
|
redir = request.values.get("redirect")
|
||||||
if redir:
|
if redir:
|
||||||
redir = redir.replace("/logged_out", "").strip()
|
redir = redir.replace("/logged_out", "").strip()
|
||||||
if not redir.startswith(f'{SITE_FULL}/') and not redir.startswith('/'): redir = '/'
|
if not redir.startswith(f'{SITE_FULL}/') and not (redir.startswith('/') and '\\' not in redir): redir = '/'
|
||||||
|
|
||||||
if redir:
|
if redir:
|
||||||
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
|
||||||
if redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
|
if redir.startswith('/') and '\\' not in redir: return redirect(f'{SITE_FULL}{redir}')
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
@app.get("/me")
|
@app.get("/me")
|
||||||
|
|
|
@ -585,7 +585,7 @@ def thumbnail_thread(pid):
|
||||||
return f"https://{fragment_url.split('https://')[1]}"
|
return f"https://{fragment_url.split('https://')[1]}"
|
||||||
elif fragment_url.startswith('//'):
|
elif fragment_url.startswith('//'):
|
||||||
return f"https:{fragment_url}"
|
return f"https:{fragment_url}"
|
||||||
elif fragment_url.startswith('/'):
|
elif fragment_url.startswith('/') and '\\' not in url:
|
||||||
parsed_url = urlparse(post_url)
|
parsed_url = urlparse(post_url)
|
||||||
return f"https://{parsed_url.netloc}{fragment_url}"
|
return f"https://{parsed_url.netloc}{fragment_url}"
|
||||||
else:
|
else:
|
||||||
|
@ -601,7 +601,8 @@ def thumbnail_thread(pid):
|
||||||
|
|
||||||
fetch_url = post.url
|
fetch_url = post.url
|
||||||
|
|
||||||
if fetch_url.startswith('/'): fetch_url = f"{SITE_FULL}{fetch_url}"
|
if fetch_url.startswith('/') and '\\' not in url:
|
||||||
|
fetch_url = f"{SITE_FULL}{fetch_url}"
|
||||||
|
|
||||||
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
|
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
|
||||||
|
|
||||||
|
@ -854,9 +855,11 @@ def api_is_repost():
|
||||||
@auth_required
|
@auth_required
|
||||||
def submit_post(v, sub=None):
|
def submit_post(v, sub=None):
|
||||||
|
|
||||||
title = request.values.get("title", "").strip()[:500].replace('','')
|
|
||||||
|
|
||||||
url = request.values.get("url", "").strip()
|
url = request.values.get("url", "").strip()
|
||||||
|
|
||||||
|
if '\\' in url: abort(400)
|
||||||
|
|
||||||
|
title = request.values.get("title", "").strip()[:500].replace('','')
|
||||||
|
|
||||||
body = request.values.get("body", "").strip().replace('','')
|
body = request.values.get("body", "").strip().replace('','')
|
||||||
|
|
||||||
|
@ -1516,7 +1519,7 @@ def api_pin_post(post_id, v):
|
||||||
def get_post_title(v):
|
def get_post_title(v):
|
||||||
|
|
||||||
url = request.values.get("url")
|
url = request.values.get("url")
|
||||||
if not url: abort(400)
|
if not url or '\\' in url: abort(400)
|
||||||
|
|
||||||
try: x = requests.get(url, headers=titleheaders, timeout=5, proxies=proxies)
|
try: x = requests.get(url, headers=titleheaders, timeout=5, proxies=proxies)
|
||||||
except: abort(400)
|
except: abort(400)
|
||||||
|
|
|
@ -641,9 +641,8 @@ def settings_profilecss(v):
|
||||||
urls = list(css_regex.finditer(profilecss)) + list(css_regex2.finditer(profilecss))
|
urls = list(css_regex.finditer(profilecss)) + list(css_regex2.finditer(profilecss))
|
||||||
for i in urls:
|
for i in urls:
|
||||||
url = i.group(1)
|
url = i.group(1)
|
||||||
if url.startswith('/'): continue
|
if not is_safe_url(url):
|
||||||
domain = tldextract.extract(url).registered_domain
|
domain = tldextract.extract(url).registered_domain
|
||||||
if domain not in approved_embed_hosts:
|
|
||||||
error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
|
error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
|
||||||
return render_template("settings_profilecss.html", error=error, v=v)
|
return render_template("settings_profilecss.html", error=error, v=v)
|
||||||
|
|
||||||
|
|
|
@ -341,9 +341,8 @@ def post_sub_css(v, sub):
|
||||||
urls = list(css_regex.finditer(css)) + list(css_regex2.finditer(css))
|
urls = list(css_regex.finditer(css)) + list(css_regex2.finditer(css))
|
||||||
for i in urls:
|
for i in urls:
|
||||||
url = i.group(1)
|
url = i.group(1)
|
||||||
if url.startswith('/'): continue
|
if not is_safe_url(url):
|
||||||
domain = tldextract.extract(url).registered_domain
|
domain = tldextract.extract(url).registered_domain
|
||||||
if domain not in approved_embed_hosts:
|
|
||||||
error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
|
error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
|
||||||
return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub, error=error)
|
return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub, error=error)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue