Merge branch 'main' of gitlab.com:bashrc2/epicyon

merge-requests/30/head
Bob Mottram 2021-10-28 21:49:02 +01:00
commit 63e6dbc0db
6 changed files with 187 additions and 55 deletions

View File

@ -237,6 +237,7 @@ from categories import updateHashtagCategories
from languages import getActorLanguages
from languages import setActorLanguages
from like import updateLikesCollection
from utils import malformedCiphertext
from utils import hasActor
from utils import setReplyIntervalHours
from utils import canReplyTo
@ -1490,10 +1491,15 @@ class PubServer(BaseHTTPRequestHandler):
# save the json for later queue processing
messageBytesDecoded = messageBytes.decode('utf-8')
if malformedCiphertext(messageBytesDecoded):
print('WARN: post contains malformed ciphertext ' +
str(originalMessageJson))
return 4
if containsInvalidLocalLinks(messageBytesDecoded):
print('WARN: post contains invalid local links ' +
str(originalMessageJson))
return 4
return 5
self.server.blockedCacheLastUpdated = \
updateBlockedCache(self.server.baseDir,
@ -5868,6 +5874,14 @@ class PubServer(BaseHTTPRequestHandler):
actorJson['featuredTags'] = \
actorJson['id'] + '/collections/tags'
randomizeActorImages(actorJson)
# add an updated timestamp to the actor
updatedTime = datetime.datetime.utcnow()
actorJson['updated'] = \
updatedTime.strftime("%Y-%m-%dT%H:%M:%SZ")
# add updated timestamp to avatar and banner
actorJson['icon']['updated'] = actorJson['updated']
actorJson['image']['updated'] = actorJson['updated']
# save the actor
saveJson(actorJson, actorFilename)
webfingerUpdate(baseDir,
nickname, domain,
@ -14402,13 +14416,13 @@ class PubServer(BaseHTTPRequestHandler):
if authorized and \
'/users/' in self.path and \
'?editblogpost=' in self.path and \
'?actor=' in self.path:
';actor=' in self.path:
messageId = self.path.split('?editblogpost=')[1]
if '?' in messageId:
messageId = messageId.split('?')[0]
actor = self.path.split('?actor=')[1]
if '?' in actor:
actor = actor.split('?')[0]
if ';' in messageId:
messageId = messageId.split(';')[0]
actor = self.path.split(';actor=')[1]
if ';' in actor:
actor = actor.split(';')[0]
nickname = getNicknameFromActor(self.path.split('?')[0])
if nickname == actor:
postUrl = \

View File

@ -3204,8 +3204,7 @@ def _checkJsonSignature(baseDir: str, queueJson: {}) -> (bool, bool):
baseDir + '/accounts/unknownContexts.txt'
unknownContext = str(originalJson['@context'])
print('unrecognized @context: ' +
unknownContext)
print('unrecognized @context: ' + unknownContext)
alreadyUnknown = False
if os.path.isfile(unknownContextsFile):
@ -3217,8 +3216,7 @@ def _checkJsonSignature(baseDir: str, queueJson: {}) -> (bool, bool):
with open(unknownContextsFile, 'a+') as unknownFile:
unknownFile.write(unknownContext + '\n')
else:
print('Unrecognized jsonld signature type: ' +
jwebsigType)
print('Unrecognized jsonld signature type: ' + jwebsigType)
unknownSignaturesFile = \
baseDir + '/accounts/unknownJsonSignatures.txt'

View File

@ -444,9 +444,11 @@ def _isPublicFeedPost(item: {}, personPosts: {}, debug: bool) -> bool:
if debug:
print('No type')
return False
if item['type'] != 'Create' and item['type'] != 'Announce':
if item['type'] != 'Create' and \
item['type'] != 'Announce' and \
item['type'] != 'Note':
if debug:
print('Not Create type')
print('Not a Create/Note/Announce type')
return False
if item.get('object'):
if isinstance(item['object'], dict):
@ -463,19 +465,27 @@ def _isPublicFeedPost(item: {}, personPosts: {}, debug: bool) -> bool:
if debug:
print('object is not a dict or string')
return False
elif item['type'] == 'Note':
if not item.get('published'):
if debug:
print('No published attribute')
return False
if not personPosts.get(item['id']):
thisItem = item
if item.get('object'):
thisItem = item['object']
# check that this is a public post
# #Public should appear in the "to" list
if isinstance(item['object'], dict):
if item['object'].get('to'):
if isinstance(thisItem, dict):
if thisItem.get('to'):
isPublic = False
for recipient in item['object']['to']:
for recipient in thisItem['to']:
if recipient.endswith('#Public'):
isPublic = True
break
if not isPublic:
return False
elif isinstance(item['object'], str):
elif isinstance(thisItem, str) or item['type'] == 'Note':
if item.get('to'):
isPublic = False
for recipient in item['to']:
@ -570,6 +580,10 @@ def _getPosts(session, outboxUrl: str, maxPosts: int,
if not _isPublicFeedPost(item, personPosts, debug):
continue
thisItem = item
if item['type'] != 'Note':
thisItem = item['object']
content = getBaseContentFromPost(item, systemLanguage)
content = content.replace(''', "'")
@ -579,9 +593,11 @@ def _getPosts(session, outboxUrl: str, maxPosts: int,
inReplyTo = ''
attachment = []
sensitive = False
if isinstance(item['object'], dict):
if item['object'].get('tag'):
for tagItem in item['object']['tag']:
if isinstance(thisItem, dict):
if thisItem.get('tag'):
for tagItem in thisItem['tag']:
if not tagItem.get('type'):
continue
tagType = tagItem['type'].lower()
if tagType == 'emoji':
if tagItem.get('name') and tagItem.get('icon'):
@ -609,25 +625,25 @@ def _getPosts(session, outboxUrl: str, maxPosts: int,
print('max emojis reached')
continue
if item['object'].get('summary'):
if item['object']['summary']:
summary = item['object']['summary']
if thisItem.get('summary'):
if thisItem['summary']:
summary = thisItem['summary']
if item['object'].get('inReplyTo'):
if item['object']['inReplyTo']:
if isinstance(item['object']['inReplyTo'], str):
if thisItem.get('inReplyTo'):
if thisItem['inReplyTo']:
if isinstance(thisItem['inReplyTo'], str):
# No replies to non-permitted domains
if not urlPermitted(item['object']['inReplyTo'],
if not urlPermitted(thisItem['inReplyTo'],
federationList):
if debug:
print('url not permitted ' +
item['object']['inReplyTo'])
thisItem['inReplyTo'])
continue
inReplyTo = item['object']['inReplyTo']
inReplyTo = thisItem['inReplyTo']
if item['object'].get('attachment'):
if item['object']['attachment']:
for attach in item['object']['attachment']:
if thisItem.get('attachment'):
if thisItem['attachment']:
for attach in thisItem['attachment']:
if attach.get('name') and attach.get('url'):
# no attachments from non-permitted domains
if urlPermitted(attach['url'],
@ -640,8 +656,8 @@ def _getPosts(session, outboxUrl: str, maxPosts: int,
attach['url'])
sensitive = False
if item['object'].get('sensitive'):
sensitive = item['object']['sensitive']
if thisItem.get('sensitive'):
sensitive = thisItem['sensitive']
if content:
if simple:
@ -773,6 +789,8 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
if item['object'].get('tag'):
for tagItem in item['object']['tag']:
if not tagItem.get('type'):
continue
tagType = tagItem['type'].lower()
if tagType == 'mention':
if tagItem.get('href'):
@ -841,21 +859,22 @@ def _getPostsForBlockedDomains(baseDir: str,
if item['object'].get('tag'):
for tagItem in item['object']['tag']:
if not tagItem.get('type'):
continue
tagType = tagItem['type'].lower()
if tagType == 'mention':
if tagItem.get('href'):
postDomain, postPort = \
getDomainFromActor(tagItem['href'])
if isBlockedDomain(baseDir, postDomain):
if item['object'].get('url'):
url = item['object']['url']
else:
url = item['object']['id']
if not blockedPosts.get(postDomain):
blockedPosts[postDomain] = [url]
else:
if url not in blockedPosts[postDomain]:
blockedPosts[postDomain].append(url)
if tagType == 'mention' and tagItem.get('href'):
postDomain, postPort = \
getDomainFromActor(tagItem['href'])
if isBlockedDomain(baseDir, postDomain):
if item['object'].get('url'):
url = item['object']['url']
else:
url = item['object']['id']
if not blockedPosts.get(postDomain):
blockedPosts[postDomain] = [url]
else:
if url not in blockedPosts[postDomain]:
blockedPosts[postDomain].append(url)
return blockedPosts

View File

@ -2537,6 +2537,16 @@ def isPGPEncrypted(content: str) -> bool:
return False
def malformedCiphertext(content: str) -> bool:
"""Returns true if the given content contains a malformed key
"""
if '----BEGIN ' in content or '----END ' in content:
if not containsPGPPublicKey(content) and \
not isPGPEncrypted(content):
return True
return False
def loadTranslationsFromFile(baseDir: str, language: str) -> ({}, str):
"""Returns the translations dictionary
"""

View File

@ -283,16 +283,34 @@ def htmlProfileAfterSearch(cssCache: {},
if isCreateInsideAnnounce(item):
isAnnouncedFeedItem = True
item = item['object']
if not item.get('actor'):
continue
if not isAnnouncedFeedItem and item['actor'] != personUrl:
continue
if not item.get('type'):
continue
if item['type'] == 'Create':
if not hasObjectDict(item):
continue
if item['type'] != 'Create' and item['type'] != 'Announce':
if item['type'] != 'Note':
continue
if not item.get('to'):
continue
if not item.get('id'):
continue
# wrap in create
cc = []
if item.get('cc'):
cc = item['cc']
newItem = {
'object': item,
'to': item['to'],
'cc': cc,
'id': item['id'],
'actor': personUrl,
'type': 'Create'
}
item = newItem
if not item.get('actor'):
continue
if not isAnnouncedFeedItem and item['actor'] != personUrl:
continue
profileStr += \

View File

@ -159,12 +159,22 @@ def createWebfingerEndpoint(nickname: str, domain: str, port: int,
profilePageHref = httpPrefix + '://' + domain + \
'/about/more?instance_actor=true'
personLink = httpPrefix + "://" + domain + "/@" + personName
account = {
"aliases": [
httpPrefix + "://" + domain + "/@" + personName,
personLink,
personId
],
"links": [
{
"href": personLink + "/avatar.png",
"rel": "http://webfinger.net/rel/avatar",
"type": "image/png"
},
{
"href": httpPrefix + "://" + domain + "/blog/" + personName,
"rel": "http://webfinger.net/rel/blog"
},
{
"href": profilePageHref,
"rel": "http://webfinger.net/rel/profile-page",
@ -242,8 +252,7 @@ def webfingerLookup(path: str, baseDir: str,
return None
if '&' in handle:
handle = handle.split('&')[0].strip()
if debug:
print('DEBUG: WEBFINGER handle with & removed ' + handle)
print('DEBUG: WEBFINGER handle with & removed ' + handle)
if '@' not in handle:
if debug:
print('DEBUG: WEBFINGER no @ in handle ' + handle)
@ -283,6 +292,64 @@ def webfingerLookup(path: str, baseDir: str,
return wfJson
def _webfingerUpdateAvatar(wfJson: {}, actorJson: {}) -> bool:
"""Updates the avatar image link
"""
found = False
avatarUrl = actorJson['icon']['url']
mediaType = actorJson['icon']['mediaType']
for link in wfJson['links']:
if not link.get('rel'):
continue
if not link['rel'].endswith('://webfinger.net/rel/avatar'):
continue
found = True
if link['href'] != avatarUrl or link['type'] != mediaType:
link['href'] = avatarUrl
link['type'] = mediaType
return True
break
if found:
return False
wfJson['links'].append({
"href": avatarUrl,
"rel": "http://webfinger.net/rel/avatar",
"type": mediaType
})
return True
def _webfingerAddBlogLink(wfJson: {}, actorJson: {}) -> bool:
"""Adds a blog link to webfinger if needed
"""
found = False
if '/users/' in actorJson['id']:
blogUrl = \
actorJson['id'].split('/users/')[0] + '/blog/' + \
actorJson['id'].split('/users/')[1]
else:
blogUrl = \
actorJson['id'].split('/@')[0] + '/blog/' + \
actorJson['id'].split('/@')[1]
for link in wfJson['links']:
if not link.get('rel'):
continue
if not link['rel'].endswith('://webfinger.net/rel/blog'):
continue
found = True
if link['href'] != blogUrl:
link['href'] = blogUrl
return True
break
if found:
return False
wfJson['links'].append({
"href": blogUrl,
"rel": "http://webfinger.net/rel/blog"
})
return True
def _webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool:
"""Updates webfinger Email/blog/xmpp links from profile
Returns true if one or more tags has been changed
@ -357,6 +424,12 @@ def _webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool:
wfJson['aliases'].remove(fullAlias)
changed = True
if _webfingerUpdateAvatar(wfJson, actorJson):
changed = True
if _webfingerAddBlogLink(wfJson, actorJson):
changed = True
return changed