Spoof gps metadata on images

merge-requests/30/head
Bob Mottram 2021-05-09 20:11:05 +01:00
parent 53fb8b9923
commit 05f1ada1c1
13 changed files with 4456 additions and 138 deletions

View File

@ -428,7 +428,7 @@ class PubServer(BaseHTTPRequestHandler):
answer, False, False, False,
commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, self.server.city,
inReplyTo,
inReplyToAtomUri,
subject,
@ -1170,7 +1170,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.debug,
self.server.YTReplacementDomain,
self.server.showPublishedDateOnly,
self.server.allowLocalNetworkAccess)
self.server.allowLocalNetworkAccess,
self.server.city)
def _postToOutboxThread(self, messageJson: {}) -> bool:
"""Creates a thread to send a post
@ -4075,8 +4076,8 @@ class PubServer(BaseHTTPRequestHandler):
os.remove(postImageFilename + '.etag')
except BaseException:
pass
processMetaData(baseDir, nickname, domain,
filename, postImageFilename)
processMetaData(baseDir, nickname,
filename, postImageFilename, self.server.city)
if os.path.isfile(postImageFilename):
print('profile update POST ' + mType +
' image or font saved to ' + postImageFilename)
@ -13055,8 +13056,8 @@ class PubServer(BaseHTTPRequestHandler):
postImageFilename = filename.replace('.temp', '')
print('Removing metadata from ' + postImageFilename)
processMetaData(self.server.baseDir,
nickname, self.server.domain,
filename, postImageFilename)
nickname, filename, postImageFilename,
self.server.city)
if os.path.isfile(postImageFilename):
print('POST media saved to ' + postImageFilename)
else:
@ -13171,6 +13172,7 @@ class PubServer(BaseHTTPRequestHandler):
False, False, False, commentsEnabled,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
fields['replyTo'], fields['replyTo'],
fields['subject'], fields['schedulePost'],
fields['eventDate'], fields['eventTime'],
@ -13316,7 +13318,8 @@ class PubServer(BaseHTTPRequestHandler):
postJsonObject['object'],
filename,
attachmentMediaType,
imgDescription)
imgDescription,
self.server.city)
replaceYouTube(postJsonObject,
self.server.YTReplacementDomain)
@ -13347,6 +13350,7 @@ class PubServer(BaseHTTPRequestHandler):
False, False, False, commentsEnabled,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
fields['replyTo'],
fields['replyTo'],
fields['subject'],
@ -13379,6 +13383,7 @@ class PubServer(BaseHTTPRequestHandler):
commentsEnabled,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
fields['replyTo'],
fields['replyTo'],
fields['subject'],
@ -13431,6 +13436,7 @@ class PubServer(BaseHTTPRequestHandler):
False, False, commentsEnabled,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
fields['subject'],
fields['schedulePost'],
fields['eventDate'],
@ -13468,6 +13474,7 @@ class PubServer(BaseHTTPRequestHandler):
commentsEnabled,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
fields['replyTo'],
fields['replyTo'],
fields['subject'],
@ -13506,6 +13513,7 @@ class PubServer(BaseHTTPRequestHandler):
True, False, False, False,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
None, None,
fields['subject'],
True, fields['schedulePost'],
@ -13538,6 +13546,7 @@ class PubServer(BaseHTTPRequestHandler):
True, False, False, True,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
self.server.debug, fields['subject'])
if messageJson:
if self._postToOutbox(messageJson, __version__, nickname):
@ -13568,6 +13577,7 @@ class PubServer(BaseHTTPRequestHandler):
commentsEnabled,
filename, attachmentMediaType,
fields['imageDescription'],
self.server.city,
fields['subject'],
int(fields['duration']))
if messageJson:
@ -13603,7 +13613,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['category'],
fields['location'],
durationStr,
self.server.debug)
self.server.debug,
self.server.city)
if filename:
if os.path.isfile(filename):
os.remove(filename)
@ -14665,7 +14676,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None:
break
def runDaemon(showNodeInfoAccounts: bool,
def runDaemon(city: str,
showNodeInfoAccounts: bool,
showNodeInfoVersion: bool,
brochMode: bool,
verifyAllSignatures: bool,
@ -14823,6 +14835,13 @@ def runDaemon(showNodeInfoAccounts: bool,
print('ERROR: no translations were loaded')
sys.exit()
# spoofed city for gps location misdirection
httpd.city = city
cityFilename = baseDir + '/accounts/city.txt'
if os.path.isfile(cityFilename):
with open(cityFilename, 'r') as fp:
httpd.city = fp.read().replace('\n', '')
# For moderated newswire feeds this is the amount of time allowed
# for voting after the post arrives
httpd.votingTimeMins = votingTimeMins

View File

@ -458,6 +458,7 @@ def _desktopReplyToPost(session, postId: str,
isArticle = False
subject = None
commentsEnabled = True
city = 'London'
sayStr = 'Sending reply'
_sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak)
if sendPostViaServer(__version__,
@ -466,7 +467,7 @@ def _desktopReplyToPost(session, postId: str,
toNickname, toDomain, toPort, ccUrl,
httpPrefix, replyMessage, followersOnly,
commentsEnabled, attach, mediaType,
attachedImageDescription,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
debug, postId, postId, subject) == 0:
sayStr = 'Reply sent'
@ -514,6 +515,7 @@ def _desktopNewPost(session,
attach = None
mediaType = None
attachedImageDescription = None
city = 'London'
isArticle = False
subject = None
commentsEnabled = True
@ -526,7 +528,7 @@ def _desktopNewPost(session,
None, '#Public', port, ccUrl,
httpPrefix, newMessage, followersOnly,
commentsEnabled, attach, mediaType,
attachedImageDescription,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
debug, None, None, subject) == 0:
sayStr = 'Post sent'
@ -1158,6 +1160,7 @@ def _desktopNewDMbase(session, toHandle: str,
attach = None
mediaType = None
attachedImageDescription = None
city = 'London'
isArticle = False
subject = None
commentsEnabled = True
@ -1206,7 +1209,7 @@ def _desktopNewDMbase(session, toHandle: str,
toNickname, toDomain, toPort, ccUrl,
httpPrefix, newMessage, followersOnly,
commentsEnabled, attach, mediaType,
attachedImageDescription,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
debug, None, None, subject) == 0:
sayStr = 'Direct message sent'

View File

@ -464,6 +464,9 @@ parser.add_argument('--attach', dest='attach', type=str,
default=None, help='File to attach to a post')
parser.add_argument('--imagedescription', dest='imageDescription', type=str,
default=None, help='Description of an attached image')
parser.add_argument('--city', dest='city', type=str,
default='London',
help='Spoofed city for image metadata misdirection')
parser.add_argument('--warning', '--warn', '--cwsubject', '--subject',
dest='subject', type=str, default=None,
help='Subject of content warning')
@ -1110,6 +1113,7 @@ if args.message:
followersOnly = args.followersonly
clientToServer = args.client
attachedImageDescription = args.imageDescription
city = 'London'
sendThreads = []
postLog = []
personCache = {}
@ -1130,7 +1134,7 @@ if args.message:
toNickname, toDomain, toPort, ccUrl,
httpPrefix, sendMessage, followersOnly,
args.commentsEnabled, attach, mediaType,
attachedImageDescription,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
args.debug, replyTo, replyTo, subject)
for i in range(10):
@ -1959,8 +1963,9 @@ if args.avatar:
if not args.nickname:
print('Specify a nickname with --nickname [name]')
sys.exit()
city = 'London'
if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
port, args.avatar, 'avatar', '128x128'):
port, args.avatar, 'avatar', '128x128', city):
print('Avatar added for ' + args.nickname)
else:
print('Avatar was not added for ' + args.nickname)
@ -1973,8 +1978,10 @@ if args.backgroundImage:
if not args.nickname:
print('Specify a nickname with --nickname [name]')
sys.exit()
city = 'London'
if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
port, args.backgroundImage, 'background', '256x256'):
port, args.backgroundImage, 'background',
'256x256', city):
print('Background image added for ' + args.nickname)
else:
print('Background image was not added for ' + args.nickname)
@ -2347,6 +2354,7 @@ if args.unfilterStr:
sys.exit()
if args.testdata:
city = 'London'
nickname = 'testuser567'
password = 'boringpassword'
print('Generating some test data for user: ' + nickname)
@ -2394,7 +2402,7 @@ if args.testdata:
"mechanical",
"City",
"2 months",
debug)
debug, city)
addShare(baseDir,
httpPrefix, nickname, domain, port,
"witch hat",
@ -2404,7 +2412,7 @@ if args.testdata:
"clothing",
"City",
"3 months",
debug)
debug, city)
deleteAllPosts(baseDir, nickname, domain, 'inbox')
deleteAllPosts(baseDir, nickname, domain, 'outbox')
@ -2416,6 +2424,7 @@ if args.testdata:
testAttachImageFilename = None
testMediaType = None
testImageDescription = None
testCity = 'London'
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"like this is totally just a #test man",
@ -2424,7 +2433,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription)
testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Zoiks!!!",
testFollowersOnly,
@ -2432,7 +2441,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription)
testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Hey scoob we need like a hundred more #milkshakes",
testFollowersOnly,
@ -2440,7 +2449,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription)
testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Getting kinda spooky around here",
testFollowersOnly,
@ -2448,7 +2457,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription,
testMediaType, testImageDescription, testCity,
'someone')
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"And they would have gotten away with it too" +
@ -2458,7 +2467,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
'img/logo.png', 'image/png',
'Description of image')
'Description of image', testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"man these centralized sites are like the worst!",
testFollowersOnly,
@ -2466,7 +2475,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription)
testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"another mystery solved #test",
testFollowersOnly,
@ -2474,7 +2483,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription)
testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"let's go bowling",
testFollowersOnly,
@ -2482,7 +2491,7 @@ if args.testdata:
testC2S,
testCommentsEnabled,
testAttachImageFilename,
testMediaType, testImageDescription)
testMediaType, testImageDescription, testCity)
domainFull = domain + ':' + str(port)
clearFollows(baseDir, nickname, domain)
@ -2620,6 +2629,11 @@ showNodeInfoVersion = \
if showNodeInfoVersion is not None:
args.showNodeInfoVersion = bool(showNodeInfoVersion)
city = \
getConfigParam(baseDir, 'city')
if city is not None:
args.city = city
YTDomain = getConfigParam(baseDir, 'youtubedomain')
if YTDomain:
if '://' in YTDomain:
@ -2634,7 +2648,8 @@ if setTheme(baseDir, themeName, domain,
print('Theme set to ' + themeName)
if __name__ == "__main__":
runDaemon(args.showNodeInfoAccounts,
runDaemon(args.city,
args.showNodeInfoAccounts,
args.showNodeInfoVersion,
args.brochMode,
args.verifyAllSignatures,

View File

@ -2183,6 +2183,7 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
attachImageFilename = None
mediaType = None
imageDescription = ''
city = 'London'
inReplyTo = removeIdEnding(senderPostId)
inReplyToAtomUri = None
schedulePost = False
@ -2195,7 +2196,7 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
saveToFile, clientToServer,
commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
inReplyTo, inReplyToAtomUri,
subject, debug, schedulePost,
eventDate, eventTime, location)

4188
locations.txt 100644

File diff suppressed because it is too large Load Diff

132
media.py
View File

@ -54,76 +54,105 @@ def _removeMetaData(imageFilename: str, outputFilename: str) -> None:
os.system('/usr/bin/mogrify -strip ' + outputFilename) # nosec
def _spoofMetaData(nickname: str,
imageFilename: str, outputFilename: str,
spoofFilename: str) -> None:
def spoofGeolocation(baseDir: str,
city: str, currTime,
citiesList: []) -> (float, float, str, str):
"""Given a city and the current time spoofs the location
for an image
returns latitude, longitude, N/S, E/W
"""
locationsFilename = baseDir + '/custom_locations.txt'
if not os.path.isfile(locationsFilename):
locationsFilename = baseDir + '/locations.txt'
variance = 0.2
default_latitude = 51.5069
default_longitude = -0.1114
default_latdirection = 'N'
default_longdirection = 'E'
if citiesList:
cities = citiesList
else:
if not os.path.isfile(locationsFilename):
return (default_latitude, default_longitude,
default_latdirection, default_longdirection)
cities = []
with open(locationsFilename, "r") as f:
cities = f.readlines()
city = city.lower()
for cityName in cities:
if city in cityName.lower():
latitude = cityName.split(':')[1]
longitude = cityName.split(':')[2]
latdirection = 'N'
longdirection = 'E'
if 'S' in latitude:
latdirection = 'S'
latitude = latitude.replace('S', '')
if 'W' in longitude:
longdirection = 'W'
longitude = longitude.replace('W', '')
# add some randomness
fraction = randint(0, 100000) / 100000
fraction = fraction * fraction
latitude = float(latitude) + \
(fraction * variance) - (variance / 2.0)
latitude = int(latitude * 10000) / 10000.0
fraction = randint(0, 100000) / 100000
fraction = fraction * fraction
longitude = float(longitude) + \
(fraction * variance) - (variance / 2.0)
longitude = int(longitude * 10000) / 10000.0
return latitude, longitude, latdirection, longdirection
return (default_latitude, default_longitude,
default_latdirection, default_longdirection)
def _spoofMetaData(baseDir: str, nickname: str,
outputFilename: str, spoofCity: str) -> None:
"""Use reference images to spoof the metadata
"""
copyfile(imageFilename, outputFilename)
if not os.path.isfile(outputFilename):
print('ERROR: unable to spoof metadata from ' + imageFilename)
return
if not os.path.isfile(spoofFilename):
print('ERROR: No spoof reference image ' + spoofFilename)
print('ERROR: unable to spoof metadata within ' + outputFilename)
return
if os.path.isfile('/usr/bin/exiftool'):
print('Spoofing metadata in ' + outputFilename + ' using exiftool')
os.system('exiftool -TagsFromFile ' +
spoofFilename + ' ' + outputFilename) # nosec
currTimeAdjusted = \
datetime.datetime.utcnow() - \
datetime.timedelta(minutes=randint(2, 120))
published = currTimeAdjusted.strftime("%Y:%m:%d %H:%M:%S+00:00")
(latitude, longitude, latitudeRef, longitudeRef) = \
spoofGeolocation(baseDir, spoofCity, currTimeAdjusted, None)
os.system('exiftool -artist="' + nickname + '" ' +
'-time:all="' + published + '" ' +
'-DateTimeOriginal="' + published + '" ' +
'-FileModifyDate="' + published + '" ' +
'-CreateDate="' + published + '" ' +
'-GPSLongitudeRef=' + longitudeRef + ' ' +
'-GPSAltitude=0 ' +
'-GPSLongitude=' + str(longitude) + ' ' +
'-GPSLatitudeRef=' + latitudeRef + ' ' +
'-GPSLatitude=' + str(latitude) + ' ' +
'-Comment="" ' +
outputFilename) # nosec
else:
print('ERROR: exiftool is not installed')
return
def processMetaData(baseDir: str, nickname: str, domain: str,
imageFilename: str, outputFilename: str) -> None:
def processMetaData(baseDir: str, nickname: str,
imageFilename: str, outputFilename: str,
city: str) -> None:
"""Handles image metadata. This tries to spoof the metadata
if possible, but otherwise just removes it
"""
accountDir = baseDir + '/accounts/' + nickname + '@' + domain
spoofImagesDir = accountDir + '/ref/images'
if os.path.isdir(spoofImagesDir):
imageTypes = getImageExtensions()
# get the format of the target image
ext = None
for mType in imageTypes:
if outputFilename.endswith('.' + mType):
ext = mType
break
if ext:
spoofList = []
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for f in files:
filename = os.path.join(spoofImagesDir, f)
# what is the format of this file?
currExt = None
for mType in imageTypes:
if filename.endswith('.' + mType):
currExt = mType
break
# if this the same format as the target?
if currExt:
if currExt == ext:
spoofList.append(filename)
break
if spoofList:
# choose a reference at random
index = randint(0, len(spoofList))
spoofFilename = spoofList[index]
_spoofMetaData(nickname,
imageFilename, outputFilename,
spoofFilename)
return
# if we can't spoof then just remove metadata
# first remove the metadata
_removeMetaData(imageFilename, outputFilename)
# now add some spoofed data to misdirect surveillance capitalists
_spoofMetaData(baseDir, nickname, outputFilename, city)
def _isMedia(imageFilename: str) -> bool:
"""Is the given file a media file?
@ -206,7 +235,8 @@ def _updateEtag(mediaFilename: str) -> None:
def attachMedia(baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int,
postJson: {}, imageFilename: str,
mediaType: str, description: str) -> {}:
mediaType: str, description: str,
city: str) -> {}:
"""Attaches media to a json object post
The description can be None
"""
@ -252,8 +282,8 @@ def attachMedia(baseDir: str, httpPrefix: str,
if baseDir:
if mediaType.startswith('image/'):
processMetaData(baseDir, nickname, domain,
imageFilename, mediaFilename)
processMetaData(baseDir, nickname,
imageFilename, mediaFilename, city)
else:
copyfile(imageFilename, mediaFilename)
_updateEtag(mediaFilename)

View File

@ -527,11 +527,17 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
# NOTE: the id when the post is created will not be
# consistent (it's based on the current time, not the
# published time), so we change that later
saveToFile = False
attachImageFilename = None
mediaType = None
imageDescription = None
city = 'London'
blog = createNewsPost(baseDir,
domain, port, httpPrefix,
rssDescription,
followersOnly, False,
None, None, None,
followersOnly, saveToFile,
attachImageFilename, mediaType,
imageDescription, city,
rssTitle)
if not blog:
continue

View File

@ -176,7 +176,8 @@ def postMessageToOutbox(session, translate: {},
proxyType: str, version: str, debug: bool,
YTReplacementDomain: str,
showPublishedDateOnly: bool,
allowLocalNetworkAccess: bool) -> bool:
allowLocalNetworkAccess: bool,
city: str) -> bool:
"""post is received by the outbox
Client to server message post
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
@ -545,7 +546,7 @@ def postMessageToOutbox(session, translate: {},
print('DEBUG: handle share uploads')
outboxShareUpload(baseDir, httpPrefix,
postToNickname, domain,
port, messageJson, debug)
port, messageJson, debug, city)
if debug:
print('DEBUG: handle undo share uploads')

View File

@ -74,7 +74,7 @@ def generateRSAKey() -> (str, str):
def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
port: int, imageFilename: str, imageType: str,
resolution: str) -> bool:
resolution: str, city: str) -> bool:
"""Saves the given image file as an avatar or background
image for the given person
"""
@ -135,8 +135,8 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
'/usr/bin/convert ' + imageFilename + ' -size ' + \
resolution + ' -quality 50 ' + profileFilename
subprocess.call(cmd, shell=True)
processMetaData(baseDir, nickname, domain,
profileFilename, profileFilename)
processMetaData(baseDir, nickname,
profileFilename, profileFilename, city)
return True
return False

View File

@ -867,7 +867,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str,
mediaType: str, imageDescription: str,
mediaType: str, imageDescription: str, city: str,
isModerationReport: bool,
isArticle: bool,
inReplyTo=None,
@ -1107,7 +1107,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
newPost['object'] = \
attachMedia(baseDir, httpPrefix, nickname, domain, port,
newPost['object'], attachImageFilename,
mediaType, imageDescription)
mediaType, imageDescription, city)
_appendEventFields(newPost['object'], eventUUID, eventStatus,
anonymousParticipationEnabled,
repliesModerationOption,
@ -1157,7 +1157,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
newPost = \
attachMedia(baseDir, httpPrefix, nickname, domain, port,
newPost, attachImageFilename,
mediaType, imageDescription)
mediaType, imageDescription, city)
_appendEventFields(newPost, eventUUID, eventStatus,
anonymousParticipationEnabled,
repliesModerationOption,
@ -1397,7 +1397,7 @@ def createPublicPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, subject=None,
schedulePost=False,
eventDate=None, eventTime=None, location=None,
@ -1423,7 +1423,7 @@ def createPublicPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
isModerationReport, isArticle,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location,
@ -1470,7 +1470,7 @@ def createBlogPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, subject=None,
schedulePost=False,
eventDate=None, eventTime=None, location=None) -> {}:
@ -1480,7 +1480,7 @@ def createBlogPost(baseDir: str,
content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
inReplyTo, inReplyToAtomUri, subject,
schedulePost,
eventDate, eventTime, location, True)
@ -1495,7 +1495,7 @@ def createNewsPost(baseDir: str,
domain: str, port: int, httpPrefix: str,
content: str, followersOnly: bool, saveToFile: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
subject: str) -> {}:
clientToServer = False
inReplyTo = None
@ -1510,7 +1510,7 @@ def createNewsPost(baseDir: str,
content, followersOnly, saveToFile,
clientToServer, False,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
inReplyTo, inReplyToAtomUri, subject,
schedulePost,
eventDate, eventTime, location, True)
@ -1524,7 +1524,7 @@ def createQuestionPost(baseDir: str,
followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
subject: str, durationDays: int) -> {}:
"""Question post with multiple choice options
"""
@ -1537,7 +1537,7 @@ def createQuestionPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
False, False, None, None, subject,
False, None, None, None, None, None,
None, None, None,
@ -1568,7 +1568,7 @@ def createUnlistedPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, subject=None,
schedulePost=False,
eventDate=None, eventTime=None, location=None) -> {}:
@ -1582,8 +1582,9 @@ def createUnlistedPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
False, False, inReplyTo, inReplyToAtomUri, subject,
imageDescription, city,
False, False,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location,
None, None, None, None, None,
None, None, None, None, None)
@ -1596,7 +1597,7 @@ def createFollowersOnlyPost(baseDir: str,
saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None,
subject=None, schedulePost=False,
eventDate=None, eventTime=None,
@ -1611,8 +1612,9 @@ def createFollowersOnlyPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
False, False, inReplyTo, inReplyToAtomUri, subject,
imageDescription, city,
False, False,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location,
None, None, None, None, None,
None, None, None, None, None)
@ -1625,7 +1627,7 @@ def createEventPost(baseDir: str,
saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
subject=None, schedulePost=False,
eventDate=None, eventTime=None,
location=None, category=None, joinMode=None,
@ -1658,7 +1660,7 @@ def createEventPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
False, False, None, None, subject,
schedulePost, eventDate, eventTime, location,
eventUUID, category, joinMode,
@ -1710,7 +1712,7 @@ def createDirectMessagePost(baseDir: str,
saveToFile: bool, clientToServer: bool,
commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None,
subject=None, debug=False,
schedulePost=False,
@ -1733,8 +1735,9 @@ def createDirectMessagePost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
False, False, inReplyTo, inReplyToAtomUri, subject,
imageDescription, city,
False, False,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location,
None, None, None, None, None,
None, None, None, None, None)
@ -1754,7 +1757,7 @@ def createReportPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
debug: bool, subject=None) -> {}:
"""Send a report to moderators
"""
@ -1823,7 +1826,7 @@ def createReportPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
True, False, None, None, subject,
False, None, None, None, None, None,
None, None, None,
@ -1908,7 +1911,7 @@ def sendPost(projectVersion: str,
saveToFile: bool, clientToServer: bool,
commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
federationList: [], sendThreads: [], postLog: [],
cachedWebfingers: {}, personCache: {},
isArticle: bool,
@ -1967,7 +1970,7 @@ def sendPost(projectVersion: str,
followersOnly, saveToFile, clientToServer,
commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
False, isArticle, inReplyTo,
inReplyToAtomUri, subject,
False, None, None, None, None, None,
@ -2029,7 +2032,7 @@ def sendPostViaServer(projectVersion: str,
httpPrefix: str, content: str, followersOnly: bool,
commentsEnabled: bool,
attachImageFilename: str, mediaType: str,
imageDescription: str,
imageDescription: str, city: str,
cachedWebfingers: {}, personCache: {},
isArticle: bool, debug=False, inReplyTo=None,
inReplyToAtomUri=None, subject=None) -> int:
@ -2106,7 +2109,7 @@ def sendPostViaServer(projectVersion: str,
followersOnly, saveToFile, clientToServer,
commentsEnabled,
attachImageFilename, mediaType,
imageDescription,
imageDescription, city,
False, isArticle, inReplyTo,
inReplyToAtomUri, subject,
False, None, None, None, None, None,

View File

@ -108,7 +108,8 @@ def _updatePostSchedule(baseDir: str, handle: str, httpd,
httpd.debug,
httpd.YTReplacementDomain,
httpd.showPublishedDateOnly,
httpd.allowLocalNetworkAccess):
httpd.allowLocalNetworkAccess,
httpd.city):
indexLines.remove(line)
os.remove(postFilename)
continue

View File

@ -73,7 +73,7 @@ def addShare(baseDir: str,
httpPrefix: str, nickname: str, domain: str, port: int,
displayName: str, summary: str, imageFilename: str,
itemType: str, itemCategory: str, location: str,
duration: str, debug: bool) -> None:
duration: str, debug: bool, city: str) -> None:
"""Adds a new share
"""
sharesFilename = baseDir + '/accounts/' + \
@ -129,8 +129,9 @@ def addShare(baseDir: str,
formats = getImageExtensions()
for ext in formats:
if imageFilename.endswith('.' + ext):
processMetaData(baseDir, nickname, domain,
imageFilename, itemIDfile + '.' + ext)
processMetaData(baseDir, nickname,
imageFilename, itemIDfile + '.' + ext,
city)
if moveImage:
os.remove(imageFilename)
imageUrl = \
@ -513,7 +514,7 @@ def sendUndoShareViaServer(baseDir: str, session,
def outboxShareUpload(baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int,
messageJson: {}, debug: bool) -> None:
messageJson: {}, debug: bool, city: str) -> None:
""" When a shared item is received by the outbox from c2s
"""
if not messageJson.get('type'):
@ -565,7 +566,7 @@ def outboxShareUpload(baseDir: str, httpPrefix: str,
messageJson['object']['itemCategory'],
messageJson['object']['location'],
messageJson['object']['duration'],
debug)
debug, city)
if debug:
print('DEBUG: shared item received via c2s')

View File

@ -10,6 +10,7 @@ import time
import os
import shutil
import json
import datetime
from time import gmtime, strftime
from pprint import pprint
from httpsig import signPostHeaders
@ -75,6 +76,7 @@ from like import likePost
from like import sendLikeViaServer
from announce import announcePublic
from announce import sendAnnounceViaServer
from media import spoofGeolocation
from media import getMediaPath
from media import getAttachmentMediaType
from delete import sendDeleteViaServer
@ -463,6 +465,7 @@ def createServerAlice(path: str, domain: str, port: int,
testAttachImageFilename = None
testMediaType = None
testImageDescription = None
testCity = 'London'
createPublicPost(path, nickname, domain, port, httpPrefix,
"No wise fish would go anywhere without a porpoise",
testFollowersOnly,
@ -471,7 +474,7 @@ def createServerAlice(path: str, domain: str, port: int,
testCommentsEnabled,
testAttachImageFilename,
testMediaType,
testImageDescription)
testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix,
"Curiouser and curiouser!",
testFollowersOnly,
@ -480,7 +483,7 @@ def createServerAlice(path: str, domain: str, port: int,
testCommentsEnabled,
testAttachImageFilename,
testMediaType,
testImageDescription)
testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix,
"In the gardens of memory, in the palace " +
"of dreams, that is where you and I shall meet",
@ -490,7 +493,7 @@ def createServerAlice(path: str, domain: str, port: int,
testCommentsEnabled,
testAttachImageFilename,
testMediaType,
testImageDescription)
testImageDescription, testCity)
global testServerAliceRunning
testServerAliceRunning = True
maxMentions = 10
@ -506,8 +509,10 @@ def createServerAlice(path: str, domain: str, port: int,
brochMode = False
showNodeInfoAccounts = True
showNodeInfoVersion = True
city = 'London'
print('Server running: Alice')
runDaemon(showNodeInfoAccounts,
runDaemon(city,
showNodeInfoAccounts,
showNodeInfoVersion,
brochMode,
verifyAllSignatures,
@ -564,6 +569,7 @@ def createServerBob(path: str, domain: str, port: int,
testAttachImageFilename = None
testImageDescription = None
testMediaType = None
testCity = 'London'
createPublicPost(path, nickname, domain, port, httpPrefix,
"It's your life, live it your way.",
testFollowersOnly,
@ -572,7 +578,7 @@ def createServerBob(path: str, domain: str, port: int,
testCommentsEnabled,
testAttachImageFilename,
testMediaType,
testImageDescription)
testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix,
"One of the things I've realised is that " +
"I am very simple",
@ -582,7 +588,7 @@ def createServerBob(path: str, domain: str, port: int,
testCommentsEnabled,
testAttachImageFilename,
testMediaType,
testImageDescription)
testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix,
"Quantum physics is a bit of a passion of mine",
testFollowersOnly,
@ -591,7 +597,7 @@ def createServerBob(path: str, domain: str, port: int,
testCommentsEnabled,
testAttachImageFilename,
testMediaType,
testImageDescription)
testImageDescription, testCity)
global testServerBobRunning
testServerBobRunning = True
maxMentions = 10
@ -607,8 +613,10 @@ def createServerBob(path: str, domain: str, port: int,
brochMode = False
showNodeInfoAccounts = True
showNodeInfoVersion = True
city = 'London'
print('Server running: Bob')
runDaemon(showNodeInfoAccounts,
runDaemon(city,
showNodeInfoAccounts,
showNodeInfoVersion,
brochMode,
verifyAllSignatures,
@ -662,8 +670,10 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
brochMode = False
showNodeInfoAccounts = True
showNodeInfoVersion = True
city = 'London'
print('Server running: Eve')
runDaemon(showNodeInfoAccounts,
runDaemon(city,
showNodeInfoAccounts,
showNodeInfoVersion,
brochMode,
verifyAllSignatures,
@ -768,6 +778,7 @@ def testPostMessageBetweenServers():
mediaType = getAttachmentMediaType(attachedImageFilename)
attachedImageDescription = 'Logo'
isArticle = False
city = 'London'
# nothing in Alice's outbox
outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox'
assert len([name for name in os.listdir(outboxPath)
@ -782,7 +793,7 @@ def testPostMessageBetweenServers():
followersOnly,
saveToFile, clientToServer, True,
attachedImageFilename, mediaType,
attachedImageDescription, federationList,
attachedImageDescription, city, federationList,
aliceSendThreads, alicePostLog, aliceCachedWebfingers,
alicePersonCache, isArticle, inReplyTo,
inReplyToAtomUri, subject)
@ -1085,13 +1096,14 @@ def testFollowBetweenServers():
aliceCachedWebfingers = {}
alicePostLog = []
isArticle = False
city = 'London'
sendResult = \
sendPost(__version__,
sessionAlice, aliceDir, 'alice', aliceDomain, alicePort,
'bob', bobDomain, bobPort, ccUrl,
httpPrefix, 'Alice message', followersOnly, saveToFile,
clientToServer, True,
None, None, None, federationList,
None, None, None, city, federationList,
aliceSendThreads, alicePostLog, aliceCachedWebfingers,
alicePersonCache, isArticle, inReplyTo,
inReplyToAtomUri, subject)
@ -1390,7 +1402,7 @@ def testCreatePerson():
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"G'day world!", False, True, clientToServer,
True, None, None, None, None,
'Not suitable for Vogons')
'Not suitable for Vogons', 'London')
os.chdir(currDir)
shutil.rmtree(baseDir)
@ -1593,6 +1605,7 @@ def testClientToServer():
attachedImageFilename = baseDir + '/img/logo.png'
mediaType = getAttachmentMediaType(attachedImageFilename)
attachedImageDescription = 'Logo'
city = 'London'
isArticle = False
cachedWebfingers = {}
personCache = {}
@ -1611,7 +1624,7 @@ def testClientToServer():
httpPrefix, 'Sent from my ActivityPub client',
followersOnly, True,
attachedImageFilename, mediaType,
attachedImageDescription,
attachedImageDescription, city,
cachedWebfingers, personCache, isArticle,
True, None, None, None)
print('sendResult: ' + str(sendResult))
@ -2822,11 +2835,21 @@ def testReplyToPublicPost() -> None:
port = 443
httpPrefix = 'https'
postId = httpPrefix + '://rat.site/users/ninjarodent/statuses/63746173435'
content = "@ninjarodent@rat.site This is a test."
followersOnly = False
saveToFile = False
clientToServer = False
commentsEnabled = True
attachImageFilename = None
mediaType = None
imageDescription = 'Some description'
city = 'London'
reply = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"@ninjarodent@rat.site This is a test.",
False, False, False, True,
None, None, False, postId)
content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
attachImageFilename, mediaType,
imageDescription, city, postId)
# print(str(reply))
assert reply['object']['content'] == \
'<p><span class=\"h-card\">' + \
@ -3244,11 +3267,20 @@ def testLinksWithinPost() -> None:
httpPrefix = 'https'
content = 'This is a test post with links.\n\n' + \
'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/\n\nhttps://freedombone.net'
followersOnly = False
saveToFile = False
clientToServer = False
commentsEnabled = True
mediaType = None
imageDescription = None
city = 'London'
postJsonObject = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
content,
False, False, False, True,
None, None, False, None)
content, followersOnly, saveToFile,
clientToServer, commentsEnabled,
mediaType, imageDescription, city,
False, None)
assert postJsonObject['object']['content'] == \
'<p>This is a test post with links.<br><br>' + \
'<a href="ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/" ' + \
@ -3636,9 +3668,27 @@ def testRemovePostInteractions() -> None:
assert not removePostInteractions(postJsonObject, False)
def testSpoofGeolocation() -> None:
print('testSpoofGeolocation')
citiesList = [
'NEW YORK, USA:40.6397:W73.7789',
'LOS ANGELES, USA:33.9425:W118.408',
'HOUSTON, USA:29.9803:W95.3397'
]
currTime = datetime.datetime.utcnow()
coords = spoofGeolocation('', 'los angeles', currTime, citiesList)
assert coords[0] >= 33.9425 - 0.1
assert coords[0] <= 33.9425 + 0.1
assert coords[1] >= 118.408 - 0.1
assert coords[1] <= 118.408 + 0.1
assert coords[2] == 'N'
assert coords[3] == 'W'
def runAllTests():
print('Running tests...')
testFunctions()
testSpoofGeolocation()
testRemovePostInteractions()
testExtractPGPPublicKey()
testEmojiImages()