\n'
optionsStr += ' \n'
optionsStr += '
\n'
+ '" ' + getBrokenLinkSubstitute() + '/>\n'
handle = getNicknameFromActor(optionsActor) + '@' + optionsDomain
optionsStr += \
' ' + translate['Options for'] + \
diff --git a/webapp_post.py b/webapp_post.py
index d4da8f7a8..3b2bf77d2 100644
--- a/webapp_post.py
+++ b/webapp_post.py
@@ -55,6 +55,7 @@ from webapp_utils import getContentWarningButton
from webapp_utils import getPostAttachmentsAsHtml
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
+from webapp_utils import getBrokenLinkSubstitute
from webapp_media import addEmbeddedElements
from webapp_question import insertQuestion
from devices import E2EEdecryptMessageFromDevice
@@ -201,14 +202,6 @@ def getAvatarImageUrl(session,
return avatarUrl
-def getBrokenLinkSubstitute() -> str:
- """Returns html used to show a default image if the link to
- an image is broken
- """
- return " onerror=\"this.onerror=null; this.src='" + \
- "/icons/avatar_default.png'\""
-
-
def getAvatarImageHtml(showAvatarOptions: bool,
nickname: str, domainFull: str,
avatarUrl: str, postActor: str,
diff --git a/webapp_utils.py b/webapp_utils.py
index b8caff443..9f2c6bf41 100644
--- a/webapp_utils.py
+++ b/webapp_utils.py
@@ -20,6 +20,14 @@ from content import addHtmlTags
from content import replaceEmojiFromTags
+def getBrokenLinkSubstitute() -> str:
+ """Returns html used to show a default image if the link to
+ an image is broken
+ """
+ return " onerror=\"this.onerror=null; this.src='" + \
+ "/icons/avatar_default.png'\""
+
+
def htmlFollowingList(cssCache: {}, baseDir: str,
followingFilename: str) -> str:
"""Returns a list of handles being followed
From eb39892e784ff50fc58139d09fc840ebf86a405b Mon Sep 17 00:00:00 2001
From: Bob Mottram
Date: Sat, 12 Dec 2020 11:25:50 +0000
Subject: [PATCH 05/24] Fewer spaces
---
webapp_post.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/webapp_post.py b/webapp_post.py
index 3b2bf77d2..e788ac6e4 100644
--- a/webapp_post.py
+++ b/webapp_post.py
@@ -213,7 +213,7 @@ def getAvatarImageHtml(showAvatarOptions: bool,
if '/users/news/' not in avatarUrl:
avatarLink = ' '
avatarLink += \
- '
\n'
From b7e8ad6e7a302e356db8336aeccc420ff2392c60 Mon Sep 17 00:00:00 2001
From: Bob Mottram
Date: Sat, 12 Dec 2020 14:23:14 +0000
Subject: [PATCH 06/24] Tidying
---
webapp_utils.py | 50 ++++++++++++++++++++-----------------------------
1 file changed, 20 insertions(+), 30 deletions(-)
diff --git a/webapp_utils.py b/webapp_utils.py
index 9f2c6bf41..71d0ec0d4 100644
--- a/webapp_utils.py
+++ b/webapp_utils.py
@@ -281,36 +281,26 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
return None
actorStr = actor.replace('/', '-')
avatarImagePath = baseDir + '/cache/avatars/' + actorStr
- if avatarUrl.endswith('.png') or \
- '.png?' in avatarUrl:
- sessionHeaders = {
- 'Accept': 'image/png'
- }
- avatarImageFilename = avatarImagePath + '.png'
- elif (avatarUrl.endswith('.jpg') or
- avatarUrl.endswith('.jpeg') or
- '.jpg?' in avatarUrl or
- '.jpeg?' in avatarUrl):
- sessionHeaders = {
- 'Accept': 'image/jpeg'
- }
- avatarImageFilename = avatarImagePath + '.jpg'
- elif avatarUrl.endswith('.gif') or '.gif?' in avatarUrl:
- sessionHeaders = {
- 'Accept': 'image/gif'
- }
- avatarImageFilename = avatarImagePath + '.gif'
- elif avatarUrl.endswith('.webp') or '.webp?' in avatarUrl:
- sessionHeaders = {
- 'Accept': 'image/webp'
- }
- avatarImageFilename = avatarImagePath + '.webp'
- elif avatarUrl.endswith('.avif') or '.avif?' in avatarUrl:
- sessionHeaders = {
- 'Accept': 'image/avif'
- }
- avatarImageFilename = avatarImagePath + '.avif'
- else:
+
+ # try different image types
+ imageFormats = {
+ 'png': 'png',
+ 'jpg': 'jpeg',
+ 'jpeg': 'jpeg',
+ 'gif': 'gif',
+ 'webp': 'webp',
+ 'avif': 'avif'
+ }
+ avatarImageFilename = None
+ for imFormat, mimeType in imageFormats.items():
+ if avatarUrl.endswith('.' + imFormat) or \
+ '.' + imFormat + '?' in avatarUrl:
+ sessionHeaders = {
+ 'Accept': 'image/' + mimeType
+ }
+ avatarImageFilename = avatarImagePath + '.' + imFormat
+
+ if not avatarImageFilename:
return None
if (not os.path.isfile(avatarImageFilename) or force) and allowDownloads:
From 071604e07f296beb852f0344edfb6858c12dabb3 Mon Sep 17 00:00:00 2001
From: Bob Mottram
Date: Sat, 12 Dec 2020 15:06:00 +0000
Subject: [PATCH 07/24] Remove any html from nickname and bio
---
daemon.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/daemon.py b/daemon.py
index 0003d6fc7..3789becc2 100644
--- a/daemon.py
+++ b/daemon.py
@@ -171,6 +171,7 @@ from shares import getSharesFeedForPerson
from shares import addShare
from shares import removeShare
from shares import expireShares
+from utils import removeHtml
from utils import setHashtagCategory
from utils import isEditor
from utils import getImageExtensions
@@ -3760,7 +3761,8 @@ class PubServer(BaseHTTPRequestHandler):
# change displayed name
if fields.get('displayNickname'):
if fields['displayNickname'] != actorJson['name']:
- actorJson['name'] = fields['displayNickname']
+ actorJson['name'] = \
+ removeHtml(fields['displayNickname'])
actorChanged = True
# change media instance status
@@ -4047,13 +4049,14 @@ class PubServer(BaseHTTPRequestHandler):
# change user bio
if fields.get('bio'):
if fields['bio'] != actorJson['summary']:
+ bioStr = removeHtml(fields['bio'])
actorTags = {}
actorJson['summary'] = \
addHtmlTags(baseDir,
httpPrefix,
nickname,
domainFull,
- fields['bio'], [], actorTags)
+ bioStr, [], actorTags)
if actorTags:
actorJson['tag'] = []
for tagName, tag in actorTags.items():
From 70528e5f0922e3681c7efd244578352b50a373f0 Mon Sep 17 00:00:00 2001
From: Bob Mottram
Date: Sat, 12 Dec 2020 15:14:17 +0000
Subject: [PATCH 08/24] Remove html from display name
---
posts.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/posts.py b/posts.py
index 359536abe..01d8b9fd6 100644
--- a/posts.py
+++ b/posts.py
@@ -266,7 +266,7 @@ def getPersonBox(baseDir: str, session, wfRequest: {},
avatarUrl = personJson['icon']['url']
displayName = None
if personJson.get('name'):
- displayName = personJson['name']
+ displayName = removeHtml(personJson['name'])
storePersonInCache(baseDir, personUrl, personJson, personCache, True)
From d3a7a2abf461e494ff1177910580e207d61af09b Mon Sep 17 00:00:00 2001
From: Bob Mottram
Date: Sat, 12 Dec 2020 15:31:28 +0000
Subject: [PATCH 09/24] Avoid arbitrary html being added to profile fields
---
donate.py | 2 ++
jami.py | 2 ++
matrix.py | 2 ++
pgp.py | 4 ++++
ssb.py | 2 ++
tox.py | 2 ++
webapp_utils.py | 3 ++-
xmpp.py | 2 ++
8 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/donate.py b/donate.py
index db68f9680..ff8d64aab 100644
--- a/donate.py
+++ b/donate.py
@@ -48,6 +48,8 @@ def setDonationUrl(actorJson: {}, donateUrl: str) -> None:
notUrl = True
if ' ' in donateUrl:
notUrl = True
+ if '<' in donateUrl:
+ notUrl = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
diff --git a/jami.py b/jami.py
index 6cc3fe3ca..5edf13f2a 100644
--- a/jami.py
+++ b/jami.py
@@ -53,6 +53,8 @@ def setJamiAddress(actorJson: {}, jamiAddress: str) -> None:
notJamiAddress = True
if ',' in jamiAddress:
notJamiAddress = True
+ if '<' in jamiAddress:
+ notJamiAddress = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
diff --git a/matrix.py b/matrix.py
index c09814ed5..4fef875cc 100644
--- a/matrix.py
+++ b/matrix.py
@@ -63,6 +63,8 @@ def setMatrixAddress(actorJson: {}, matrixAddress: str) -> None:
return
if '"' in matrixAddress:
return
+ if '<' in matrixAddress:
+ return
if ':' not in matrixAddress:
return
diff --git a/pgp.py b/pgp.py
index f8dad7261..3a25de50b 100644
--- a/pgp.py
+++ b/pgp.py
@@ -83,6 +83,8 @@ def setEmailAddress(actorJson: {}, emailAddress: str) -> None:
notEmailAddress = True
if '.' not in emailAddress:
notEmailAddress = True
+ if '<' in emailAddress:
+ notEmailAddress = True
if emailAddress.startswith('@'):
notEmailAddress = True
@@ -134,6 +136,8 @@ def setPGPpubKey(actorJson: {}, PGPpubKey: str) -> None:
else:
if '--BEGIN PGP PUBLIC KEY' not in PGPpubKey:
removeKey = True
+ if '<' in PGPpubKey:
+ removeKey = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
diff --git a/ssb.py b/ssb.py
index 93f2e4935..74804013f 100644
--- a/ssb.py
+++ b/ssb.py
@@ -52,6 +52,8 @@ def setSSBAddress(actorJson: {}, ssbAddress: str) -> None:
notSSBAddress = True
if ',' in ssbAddress:
notSSBAddress = True
+ if '<' in ssbAddress:
+ notSSBAddress = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
diff --git a/tox.py b/tox.py
index 1be44754d..2281f4f87 100644
--- a/tox.py
+++ b/tox.py
@@ -57,6 +57,8 @@ def setToxAddress(actorJson: {}, toxAddress: str) -> None:
notToxAddress = True
if ',' in toxAddress:
notToxAddress = True
+ if '<' in toxAddress:
+ notToxAddress = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
diff --git a/webapp_utils.py b/webapp_utils.py
index 71d0ec0d4..ce54a0f49 100644
--- a/webapp_utils.py
+++ b/webapp_utils.py
@@ -9,6 +9,7 @@ __status__ = "Production"
import os
from collections import OrderedDict
from session import getJson
+from utils import removeHtml
from utils import getImageExtensions
from utils import getProtocolPrefixes
from utils import loadJson
@@ -268,7 +269,7 @@ def setActorPropertyUrl(actorJson: {}, propertyName: str, url: str) -> None:
def setBlogAddress(actorJson: {}, blogAddress: str) -> None:
"""Sets an blog address for the given actor
"""
- setActorPropertyUrl(actorJson, 'Blog', blogAddress)
+ setActorPropertyUrl(actorJson, 'Blog', removeHtml(blogAddress))
def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
diff --git a/xmpp.py b/xmpp.py
index 7972a4ad1..661ae92d2 100644
--- a/xmpp.py
+++ b/xmpp.py
@@ -43,6 +43,8 @@ def setXmppAddress(actorJson: {}, xmppAddress: str) -> None:
notXmppAddress = True
if '"' in xmppAddress:
notXmppAddress = True
+ if '<' in xmppAddress:
+ notXmppAddress = True
if not actorJson.get('attachment'):
actorJson['attachment'] = []
From 8c3ecf2e94b6a067e6e658d2619844e647715c25 Mon Sep 17 00:00:00 2001
From: Bob Mottram
Date: Sat, 12 Dec 2020 15:36:44 +0000
Subject: [PATCH 10/24] Even if other instances include arbitrary html within
profile tags it isn't rendered within person options
---
webapp_person_options.py | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/webapp_person_options.py b/webapp_person_options.py
index 89e142d03..aa60ed3e1 100644
--- a/webapp_person_options.py
+++ b/webapp_person_options.py
@@ -11,6 +11,7 @@ from shutil import copyfile
from petnames import getPetName
from person import isPersonSnoozed
from posts import isModerator
+from utils import removeHtml
from utils import getDomainFromActor
from utils import getNicknameFromActor
from blocking import isBlocked
@@ -113,35 +114,36 @@ def htmlPersonOptions(defaultTimeline: str,
optionsStr += \
'' + translate['Email'] + \
': ' + emailAddress + '
\n'
+ emailAddress + '">' + removeHtml(emailAddress) + '
\n'
if xmppAddress:
optionsStr += \
'' + translate['XMPP'] + \
- ': ' + \
+ ': ' + \
xmppAddress + '
\n'
if matrixAddress:
optionsStr += \
'' + translate['Matrix'] + ': ' + \
- matrixAddress + '
\n'
+ removeHtml(matrixAddress) + '