main
Bob Mottram 2021-02-16 11:47:40 +00:00
commit e72cbecf50
8 changed files with 137 additions and 34 deletions

View File

@ -23,4 +23,4 @@ clean:
rm -f deploy/*~
rm -f translations/*~
rm -rf __pycache__
rm calendar.css blog.css epicyon.css follow.css login.css options.css search.css suspended.css
rm -f calendar.css blog.css epicyon.css follow.css login.css options.css search.css suspended.css

View File

@ -8,11 +8,45 @@ __status__ = "Production"
import os
import datetime
from session import urlExists
from utils import loadJson
from utils import saveJson
from utils import getFileCaseInsensitive
def _removePersonFromCache(baseDir: str, personUrl: str,
personCache: {}) -> bool:
"""Removes an actor from the cache
"""
cacheFilename = baseDir + '/cache/actors/' + \
personUrl.replace('/', '#')+'.json'
if os.path.isfile(cacheFilename):
try:
os.remove(cacheFilename)
except BaseException:
pass
if personCache.get(personUrl):
del personCache[personUrl]
def checkForChangedActor(session, baseDir: str,
httpPrefix: str, domainFull: str,
personUrl: str, avatarUrl: str, personCache: {},
timeoutSec: int):
"""Checks if the avatar url exists and if not then
the actor has probably changed without receiving an actor/Person Update.
So clear the actor from the cache and it will be refreshed when the next
post from them is sent
"""
if not session or not avatarUrl:
return
if domainFull in avatarUrl:
return
if urlExists(session, avatarUrl, timeoutSec, httpPrefix, domainFull):
return
_removePersonFromCache(baseDir, personUrl, personCache)
def storePersonInCache(baseDir: str, personUrl: str,
personJson: {}, personCache: {},
allowWriteToFile: bool) -> None:

View File

@ -228,6 +228,7 @@ from content import extractMediaInFormPOST
from content import saveMediaInFormPOST
from content import extractTextFieldsInPOST
from media import removeMetaData
from cache import checkForChangedActor
from cache import storePersonInCache
from cache import getPersonFromCache
from httpsig import verifyPostHeaders
@ -5488,6 +5489,15 @@ class PubServer(BaseHTTPRequestHandler):
PGPfingerprint = getPGPfingerprint(actorJson)
if actorJson.get('alsoKnownAs'):
alsoKnownAs = actorJson['alsoKnownAs']
if self.server.session:
checkForChangedActor(self.server.session,
self.server.baseDir,
self.server.httpPrefix,
self.server.domainFull,
optionsActor, optionsProfileUrl,
self.server.personCache, 5)
msg = htmlPersonOptions(self.server.defaultTimeline,
self.server.cssCache,
self.server.translate,
@ -10051,6 +10061,16 @@ class PubServer(BaseHTTPRequestHandler):
# replace https://domain/@nick with https://domain/users/nick
if self.path.startswith('/@'):
self.path = self.path.replace('/@', '/users/')
# replace https://domain/@nick/statusnumber
# with https://domain/users/nick/statuses/statusnumber
nickname = self.path.split('/users/')[1]
if '/' in nickname:
statusNumberStr = nickname.split('/')[1]
if statusNumberStr.isdigit():
nickname = nickname.split('/')[0]
self.path = \
self.path.replace('/users/' + nickname + '/',
'/users/' + nickname + '/statuses/')
# turn off dropdowns on new post screen
noDropDown = False

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -2726,6 +2726,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: checking http header signature')
pprint(queueJson['httpHeaders'])
postStr = json.dumps(queueJson['post'])
httpSignatureFailed = False
if not verifyPostHeaders(httpPrefix,
pubKey,
queueJson['httpHeaders'],
@ -2733,19 +2734,17 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queueJson['digest'],
postStr,
debug):
httpSignatureFailed = True
print('Queue: Header signature check failed')
pprint(queueJson['httpHeaders'])
if os.path.isfile(queueFilename):
os.remove(queueFilename)
if len(queue) > 0:
queue.pop(0)
continue
if debug:
print('DEBUG: http header signature check success')
if debug:
pprint(queueJson['httpHeaders'])
else:
if debug:
print('DEBUG: http header signature check success')
# check if a json signature exists on this post
checkJsonSignature = False
hasJsonSignature = False
jwebsigType = None
originalJson = queueJson['original']
if originalJson.get('@context') and \
originalJson.get('signature'):
@ -2754,41 +2753,59 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
jwebsig = originalJson['signature']
# signature exists and is of the expected type
if jwebsig.get('type') and jwebsig.get('signatureValue'):
if jwebsig['type'] == 'RsaSignature2017':
jwebsigType = jwebsig['type']
if jwebsigType == 'RsaSignature2017':
if hasValidContext(originalJson):
checkJsonSignature = True
hasJsonSignature = True
else:
print('unrecognised @context: ' +
str(originalJson['@context']))
# strict enforcement of json signatures
if verifyAllSignatures and \
not checkJsonSignature:
print('inbox post does not have a jsonld signature ' +
keyId + ' ' + str(originalJson))
if os.path.isfile(queueFilename):
os.remove(queueFilename)
if len(queue) > 0:
queue.pop(0)
continue
if checkJsonSignature and verifyAllSignatures:
# use the original json message received, not one which may have
# been modified along the way
if not verifyJsonSignature(originalJson, pubKey):
if debug:
print('WARN: jsonld inbox signature check failed ' +
keyId + ' ' + pubKey + ' ' + str(originalJson))
if not hasJsonSignature:
if httpSignatureFailed:
if jwebsigType:
print('Queue: Header signature check failed and does ' +
'not have a recognised jsonld signature type ' +
jwebsigType)
else:
print('WARN: jsonld inbox signature check failed ' +
keyId)
print('Queue: Header signature check failed and ' +
'does not have jsonld signature')
if debug:
pprint(queueJson['httpHeaders'])
if verifyAllSignatures:
print('Queue: inbox post does not have a jsonld signature ' +
keyId + ' ' + str(originalJson))
if httpSignatureFailed or verifyAllSignatures:
if os.path.isfile(queueFilename):
os.remove(queueFilename)
if len(queue) > 0:
queue.pop(0)
continue
else:
print('jsonld inbox signature check success ' + keyId)
else:
if httpSignatureFailed or verifyAllSignatures:
# use the original json message received, not one which
# may have been modified along the way
if not verifyJsonSignature(originalJson, pubKey):
if debug:
print('WARN: jsonld inbox signature check failed ' +
keyId + ' ' + pubKey + ' ' + str(originalJson))
else:
print('WARN: jsonld inbox signature check failed ' +
keyId)
if os.path.isfile(queueFilename):
os.remove(queueFilename)
if len(queue) > 0:
queue.pop(0)
continue
else:
if httpSignatureFailed:
print('jsonld inbox signature check success ' +
'via relay ' + keyId)
else:
print('jsonld inbox signature check success ' + keyId)
# set the id to the same as the post filename
# This makes the filename and the id consistent

View File

@ -53,6 +53,37 @@ def createSession(proxyType: str):
return session
def urlExists(session, url: str, timeoutSec=3,
httpPrefix='https', domain='testdomain') -> bool:
if not isinstance(url, str):
print('url: ' + str(url))
print('ERROR: urlExists failed, url should be a string')
return False
sessionParams = {}
sessionHeaders = {}
sessionHeaders['User-Agent'] = 'Epicyon/' + __version__
if domain:
sessionHeaders['User-Agent'] += \
'; +' + httpPrefix + '://' + domain + '/'
if not session:
print('WARN: urlExists failed, no session specified')
return True
try:
result = session.get(url, headers=sessionHeaders,
params=sessionParams,
timeout=timeoutSec)
if result:
if result.status_code == 200 or \
result.status_code == 304:
return True
else:
print('urlExists for ' + url + ' returned ' +
str(result.status_code))
except BaseException:
pass
return False
def getJson(session, url: str, headers: {}, params: {},
version='1.2.0', httpPrefix='https',
domain='testdomain') -> {}:
@ -72,6 +103,7 @@ def getJson(session, url: str, headers: {}, params: {},
'; +' + httpPrefix + '://' + domain + '/'
if not session:
print('WARN: getJson failed, no session specified for getJson')
return None
try:
result = session.get(url, headers=sessionHeaders, params=sessionParams)
return result.json()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 131 KiB