mirror of https://gitlab.com/bashrc2/epicyon
Merge
commit
e72cbecf50
2
Makefile
2
Makefile
|
|
@ -23,4 +23,4 @@ clean:
|
||||||
rm -f deploy/*~
|
rm -f deploy/*~
|
||||||
rm -f translations/*~
|
rm -f translations/*~
|
||||||
rm -rf __pycache__
|
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
|
||||||
|
|
|
||||||
34
cache.py
34
cache.py
|
|
@ -8,11 +8,45 @@ __status__ = "Production"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
|
from session import urlExists
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
from utils import saveJson
|
from utils import saveJson
|
||||||
from utils import getFileCaseInsensitive
|
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,
|
def storePersonInCache(baseDir: str, personUrl: str,
|
||||||
personJson: {}, personCache: {},
|
personJson: {}, personCache: {},
|
||||||
allowWriteToFile: bool) -> None:
|
allowWriteToFile: bool) -> None:
|
||||||
|
|
|
||||||
20
daemon.py
20
daemon.py
|
|
@ -228,6 +228,7 @@ from content import extractMediaInFormPOST
|
||||||
from content import saveMediaInFormPOST
|
from content import saveMediaInFormPOST
|
||||||
from content import extractTextFieldsInPOST
|
from content import extractTextFieldsInPOST
|
||||||
from media import removeMetaData
|
from media import removeMetaData
|
||||||
|
from cache import checkForChangedActor
|
||||||
from cache import storePersonInCache
|
from cache import storePersonInCache
|
||||||
from cache import getPersonFromCache
|
from cache import getPersonFromCache
|
||||||
from httpsig import verifyPostHeaders
|
from httpsig import verifyPostHeaders
|
||||||
|
|
@ -5488,6 +5489,15 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
PGPfingerprint = getPGPfingerprint(actorJson)
|
PGPfingerprint = getPGPfingerprint(actorJson)
|
||||||
if actorJson.get('alsoKnownAs'):
|
if actorJson.get('alsoKnownAs'):
|
||||||
alsoKnownAs = actorJson['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,
|
msg = htmlPersonOptions(self.server.defaultTimeline,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
self.server.translate,
|
self.server.translate,
|
||||||
|
|
@ -10051,6 +10061,16 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
# replace https://domain/@nick with https://domain/users/nick
|
# replace https://domain/@nick with https://domain/users/nick
|
||||||
if self.path.startswith('/@'):
|
if self.path.startswith('/@'):
|
||||||
self.path = self.path.replace('/@', '/users/')
|
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
|
# turn off dropdowns on new post screen
|
||||||
noDropDown = False
|
noDropDown = False
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
49
inbox.py
49
inbox.py
|
|
@ -2726,6 +2726,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
print('DEBUG: checking http header signature')
|
print('DEBUG: checking http header signature')
|
||||||
pprint(queueJson['httpHeaders'])
|
pprint(queueJson['httpHeaders'])
|
||||||
postStr = json.dumps(queueJson['post'])
|
postStr = json.dumps(queueJson['post'])
|
||||||
|
httpSignatureFailed = False
|
||||||
if not verifyPostHeaders(httpPrefix,
|
if not verifyPostHeaders(httpPrefix,
|
||||||
pubKey,
|
pubKey,
|
||||||
queueJson['httpHeaders'],
|
queueJson['httpHeaders'],
|
||||||
|
|
@ -2733,19 +2734,17 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
queueJson['digest'],
|
queueJson['digest'],
|
||||||
postStr,
|
postStr,
|
||||||
debug):
|
debug):
|
||||||
|
httpSignatureFailed = True
|
||||||
print('Queue: Header signature check failed')
|
print('Queue: Header signature check failed')
|
||||||
|
if debug:
|
||||||
pprint(queueJson['httpHeaders'])
|
pprint(queueJson['httpHeaders'])
|
||||||
if os.path.isfile(queueFilename):
|
else:
|
||||||
os.remove(queueFilename)
|
|
||||||
if len(queue) > 0:
|
|
||||||
queue.pop(0)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: http header signature check success')
|
print('DEBUG: http header signature check success')
|
||||||
|
|
||||||
# check if a json signature exists on this post
|
# check if a json signature exists on this post
|
||||||
checkJsonSignature = False
|
hasJsonSignature = False
|
||||||
|
jwebsigType = None
|
||||||
originalJson = queueJson['original']
|
originalJson = queueJson['original']
|
||||||
if originalJson.get('@context') and \
|
if originalJson.get('@context') and \
|
||||||
originalJson.get('signature'):
|
originalJson.get('signature'):
|
||||||
|
|
@ -2754,27 +2753,41 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
jwebsig = originalJson['signature']
|
jwebsig = originalJson['signature']
|
||||||
# signature exists and is of the expected type
|
# signature exists and is of the expected type
|
||||||
if jwebsig.get('type') and jwebsig.get('signatureValue'):
|
if jwebsig.get('type') and jwebsig.get('signatureValue'):
|
||||||
if jwebsig['type'] == 'RsaSignature2017':
|
jwebsigType = jwebsig['type']
|
||||||
|
if jwebsigType == 'RsaSignature2017':
|
||||||
if hasValidContext(originalJson):
|
if hasValidContext(originalJson):
|
||||||
checkJsonSignature = True
|
hasJsonSignature = True
|
||||||
else:
|
else:
|
||||||
print('unrecognised @context: ' +
|
print('unrecognised @context: ' +
|
||||||
str(originalJson['@context']))
|
str(originalJson['@context']))
|
||||||
|
|
||||||
# strict enforcement of json signatures
|
# strict enforcement of json signatures
|
||||||
if verifyAllSignatures and \
|
if not hasJsonSignature:
|
||||||
not checkJsonSignature:
|
if httpSignatureFailed:
|
||||||
print('inbox post does not have a jsonld signature ' +
|
if jwebsigType:
|
||||||
|
print('Queue: Header signature check failed and does ' +
|
||||||
|
'not have a recognised jsonld signature type ' +
|
||||||
|
jwebsigType)
|
||||||
|
else:
|
||||||
|
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))
|
keyId + ' ' + str(originalJson))
|
||||||
|
|
||||||
|
if httpSignatureFailed or verifyAllSignatures:
|
||||||
if os.path.isfile(queueFilename):
|
if os.path.isfile(queueFilename):
|
||||||
os.remove(queueFilename)
|
os.remove(queueFilename)
|
||||||
if len(queue) > 0:
|
if len(queue) > 0:
|
||||||
queue.pop(0)
|
queue.pop(0)
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
if checkJsonSignature and verifyAllSignatures:
|
if httpSignatureFailed or verifyAllSignatures:
|
||||||
# use the original json message received, not one which may have
|
# use the original json message received, not one which
|
||||||
# been modified along the way
|
# may have been modified along the way
|
||||||
if not verifyJsonSignature(originalJson, pubKey):
|
if not verifyJsonSignature(originalJson, pubKey):
|
||||||
if debug:
|
if debug:
|
||||||
print('WARN: jsonld inbox signature check failed ' +
|
print('WARN: jsonld inbox signature check failed ' +
|
||||||
|
|
@ -2787,6 +2800,10 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
if len(queue) > 0:
|
if len(queue) > 0:
|
||||||
queue.pop(0)
|
queue.pop(0)
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
if httpSignatureFailed:
|
||||||
|
print('jsonld inbox signature check success ' +
|
||||||
|
'via relay ' + keyId)
|
||||||
else:
|
else:
|
||||||
print('jsonld inbox signature check success ' + keyId)
|
print('jsonld inbox signature check success ' + keyId)
|
||||||
|
|
||||||
|
|
|
||||||
32
session.py
32
session.py
|
|
@ -53,6 +53,37 @@ def createSession(proxyType: str):
|
||||||
return session
|
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: {},
|
def getJson(session, url: str, headers: {}, params: {},
|
||||||
version='1.2.0', httpPrefix='https',
|
version='1.2.0', httpPrefix='https',
|
||||||
domain='testdomain') -> {}:
|
domain='testdomain') -> {}:
|
||||||
|
|
@ -72,6 +103,7 @@ def getJson(session, url: str, headers: {}, params: {},
|
||||||
'; +' + httpPrefix + '://' + domain + '/'
|
'; +' + httpPrefix + '://' + domain + '/'
|
||||||
if not session:
|
if not session:
|
||||||
print('WARN: getJson failed, no session specified for getJson')
|
print('WARN: getJson failed, no session specified for getJson')
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
result = session.get(url, headers=sessionHeaders, params=sessionParams)
|
result = session.get(url, headers=sessionHeaders, params=sessionParams)
|
||||||
return result.json()
|
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 |
Loading…
Reference in New Issue