[preview] Add map preview for locations provided by geo:-URIs

This commit is contained in:
Daniel
2018-02-28 13:57:43 +01:00
committed by Philipp Hörist
parent cfc13d011d
commit fcbf425309
2 changed files with 116 additions and 36 deletions

View File

@@ -39,6 +39,11 @@ class UrlImagePreviewConfigDialog(OptionsDialog):
(_('Open Link in Browser'), 'open_link_in_browser_menuitem'), (_('Open Link in Browser'), 'open_link_in_browser_menuitem'),
(_('Open File in Browser'), 'open_file_in_browser_menuitem')] (_('Open File in Browser'), 'open_file_in_browser_menuitem')]
geo_providers = [
(_('No map preview'), 'no_preview'),
('Google Maps', 'Google'),
('OpenStreetMap', 'OSM')]
self.plugin = plugin self.plugin = plugin
options = [ options = [
Option('PreviewSizeSpinOption', _('Preview size'), Option('PreviewSizeSpinOption', _('Preview size'),
@@ -58,6 +63,12 @@ class UrlImagePreviewConfigDialog(OptionsDialog):
props={'items': actions, props={'items': actions,
'plugin': self.plugin}), 'plugin': self.plugin}),
Option('PreviewComboOption', _('Map service for preview'),
OptionType.VALUE, self.plugin.config['GEO_PREVIEW_PROVIDER'],
callback=self.on_option, data='GEO_PREVIEW_PROVIDER',
props={'items': geo_providers,
'plugin': self.plugin}),
Option(OptionKind.SWITCH, _('Enable HTTPS Verification'), Option(OptionKind.SWITCH, _('Enable HTTPS Verification'),
OptionType.VALUE, self.plugin.config['VERIFY'], OptionType.VALUE, self.plugin.config['VERIFY'],
callback=self.on_option, data='VERIFY'), callback=self.on_option, data='VERIFY'),

View File

@@ -83,6 +83,7 @@ class UrlImagePreviewPlugin(GajimPlugin):
'MAX_FILE_SIZE': (524288, 'Max file size for image preview'), 'MAX_FILE_SIZE': (524288, 'Max file size for image preview'),
'LEFTCLICK_ACTION': ('open_menuitem', 'Open'), 'LEFTCLICK_ACTION': ('open_menuitem', 'Open'),
'ANONYMOUS_MUC': (False, ''), 'ANONYMOUS_MUC': (False, ''),
'GEO_PREVIEW_PROVIDER': ('Google', 'Google Maps'),
'VERIFY': (True, ''),} 'VERIFY': (True, ''),}
self.controls = {} self.controls = {}
self.history_window_control = None self.history_window_control = None
@@ -161,11 +162,14 @@ class Base(object):
def print_real_text(self, real_text, text_tags, graphics, iter_, def print_real_text(self, real_text, text_tags, graphics, iter_,
additional_data): additional_data):
urlparts = urlparse(real_text) urlparts = urlparse(real_text)
if (urlparts.scheme not in ["https", "aesgcm"] or if urlparts.scheme == "geo":
not urlparts.netloc): if self.plugin.config['GEO_PREVIEW_PROVIDER'] == 'no_preview':
log.info("Not accepting URL scheme '%s' for image preview: %s", return
urlparts.scheme, real_text) elif (urlparts.scheme not in ["https", "aesgcm"] or not urlparts.netloc):
return if urlparts.scheme != "geo":
log.info("Not accepting URL scheme '%s' for image preview: %s",
urlparts.scheme, real_text)
return
try: try:
oob_url = additional_data["gajim"]["oob_url"] oob_url = additional_data["gajim"]["oob_url"]
@@ -175,10 +179,11 @@ class Base(object):
# allow aesgcm uris without oob marker (aesgcm uris are always # allow aesgcm uris without oob marker (aesgcm uris are always
# httpupload filetransfers) # httpupload filetransfers)
if urlparts.scheme != "aesgcm" and real_text != oob_url: if urlparts.scheme != "aesgcm" and real_text != oob_url:
log.info("Not accepting URL for image preview " if urlparts.scheme != "geo":
"(wrong or no oob data): %s", real_text) log.info("Not accepting URL for image preview "
log.debug("additional_data: %s", additional_data) "(wrong or no oob data): %s", real_text)
return log.debug("additional_data: %s", additional_data)
return
# Don't print the URL in the message window (in the calling function) # Don't print the URL in the message window (in the calling function)
self.textview.plugin_modified = True self.textview.plugin_modified = True
@@ -194,35 +199,88 @@ class Base(object):
*[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]]) *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
repl_end = buffer_.create_mark(None, iter_, True) repl_end = buffer_.create_mark(None, iter_, True)
filename = os.path.basename(urlparts.path) if not real_text.startswith('geo:'):
ext = os.path.splitext(filename)[1] weburl = real_text
name = os.path.splitext(filename)[0] filename = os.path.basename(urlparts.path)
namehash = hashlib.sha1(real_text.encode('utf-8')).hexdigest() ext = os.path.splitext(filename)[1]
newfilename = name + '_' + namehash + ext name = os.path.splitext(filename)[0]
thumbfilename = name + '_' + namehash + '_thumb_' \ namehash = hashlib.sha1(real_text.encode('utf-8')).hexdigest()
+ str(self.plugin.config['PREVIEW_SIZE']) + ext newfilename = name + '_' + namehash + ext
thumbfilename = name + '_' + namehash + '_thumb_' \
+ str(self.plugin.config['PREVIEW_SIZE']) + ext
filepath = os.path.join(self.directory, newfilename) filepath = os.path.join(self.directory, newfilename)
thumbpath = os.path.join(self.thumbpath, thumbfilename) thumbpath = os.path.join(self.thumbpath, thumbfilename)
filepaths = [filepath, thumbpath] filepaths = [filepath, thumbpath]
key = '' key = ''
iv = '' iv = ''
encrypted = False encrypted = False
if urlparts.fragment: if urlparts.fragment:
fragment = binascii.unhexlify(urlparts.fragment) fragment = binascii.unhexlify(urlparts.fragment)
key = fragment[16:] key = fragment[16:]
iv = fragment[:16] iv = fragment[:16]
if len(key) == 32 and len(iv) == 16: if len(key) == 32 and len(iv) == 16:
encrypted = True
if not encrypted:
key = fragment[12:]
iv = fragment[:12]
if len(key) == 32 and len(iv) == 12:
encrypted = True encrypted = True
if not encrypted:
key = fragment[12:]
iv = fragment[:12]
if len(key) == 32 and len(iv) == 12:
encrypted = True
# Handle geo:-URIs
if real_text.startswith('geo:'):
if self.plugin.config['GEO_PREVIEW_PROVIDER'] == 'no_preview':
return
size = self.plugin.config['PREVIEW_SIZE']
geo_provider = self.plugin.config['GEO_PREVIEW_PROVIDER']
key = ''
iv = ''
encrypted = False
ext = '.png'
color = 'blue'
zoom = 16
location = real_text[4:]
lat, _, lon = location.partition(',')
if lon == '':
return
filename = 'location_' + geo_provider + '_' \
+ location.replace(',', '_').replace('.', '-')
newfilename = filename + ext
thumbfilename = filename + '_thumb_' \
+ str(self.plugin.config['PREVIEW_SIZE']) + ext
filepath = os.path.join(self.directory, newfilename)
thumbpath = os.path.join(self.thumbpath, thumbfilename)
filepaths = [filepath, thumbpath]
# Google
if geo_provider == 'Google':
url = 'https://maps.googleapis.com/maps/api/staticmap?' \
'center={}&zoom={}&size={}x{}&markers=color:{}' \
'|label:.|{}'.format(location, zoom, size, size,
color, location)
weburl = 'https://www.google.com/maps/place/{}' \
.format(location)
real_text = url
else:
# OpenStreetMap / MapQuest
apikey = 'F7x36jLVv2hiANVAXmhwvUB044XvGASh'
url = 'https://open.mapquestapi.com/staticmap/v4/' \
'getmap?key={}&center={}&zoom={}&size={},{}&type=map' \
'&imagetype=png&pois={},{}&scalebar=false' \
.format(apikey, location, zoom, size, size, color,
location)
weburl = 'http://www.openstreetmap.org/' \
'?mlat={}&mlon={}#map={}/{}/{}&layers=N' \
.format(lat, lon, zoom, lat, lon)
real_text = url
# file exists but thumbnail got deleted # file exists but thumbnail got deleted
if os.path.exists(filepath) and not os.path.exists(thumbpath): if os.path.exists(filepath) and not os.path.exists(thumbpath):
if urlparts.scheme == 'geo':
real_text = weburl
with open(filepath, 'rb') as f: with open(filepath, 'rb') as f:
mem = f.read() mem = f.read()
app.thread_interface( app.thread_interface(
@@ -233,6 +291,8 @@ class Base(object):
# display thumbnail if already downloadeded # display thumbnail if already downloadeded
# (but only if file also exists) # (but only if file also exists)
elif os.path.exists(filepath) and os.path.exists(thumbpath): elif os.path.exists(filepath) and os.path.exists(thumbpath):
if urlparts.scheme == 'geo':
real_text = weburl
app.thread_interface( app.thread_interface(
self._load_thumbnail, [thumbpath], self._load_thumbnail, [thumbpath],
self._update_img, [real_text, repl_start, self._update_img, [real_text, repl_start,
@@ -251,8 +311,9 @@ class Base(object):
verify = self.plugin.config['VERIFY'] verify = self.plugin.config['VERIFY']
app.thread_interface( app.thread_interface(
get_http_head, [self.textview.account, real_text, verify], get_http_head, [self.textview.account, real_text, verify],
self._check_mime_size, [real_text, repl_start, repl_end, self._check_mime_size, [real_text, weburl, repl_start,
filepaths, key, iv, encrypted]) repl_end, filepaths, key, iv,
encrypted])
def _save_thumbnail(self, thumbpath, mem): def _save_thumbnail(self, thumbpath, mem):
size = self.plugin.config['PREVIEW_SIZE'] size = self.plugin.config['PREVIEW_SIZE']
@@ -349,6 +410,9 @@ class Base(object):
urlparts = urlparse(url) urlparts = urlparse(url)
filename = os.path.basename(urlparts.path) filename = os.path.basename(urlparts.path)
if os.path.basename(filepath).startswith('location_'):
filename = os.path.basename(filepath)
event_box = Gtk.EventBox() event_box = Gtk.EventBox()
event_box.connect('button-press-event', self.on_button_press_event, event_box.connect('button-press-event', self.on_button_press_event,
filepath, filename, url, encrypted) filepath, filename, url, encrypted)
@@ -392,7 +456,7 @@ class Base(object):
GLib.idle_add(add_to_textview) GLib.idle_add(add_to_textview)
def _check_mime_size(self, tuple_arg, def _check_mime_size(self, tuple_arg,
url, repl_start, repl_end, filepaths, url, weburl, repl_start, repl_end, filepaths,
key, iv, encrypted): key, iv, encrypted):
file_mime, file_size = tuple_arg file_mime, file_size = tuple_arg
# Check if mime type is acceptable # Check if mime type is acceptable
@@ -424,7 +488,7 @@ class Base(object):
app.thread_interface( app.thread_interface(
self._download_image, [self.textview.account, self._download_image, [self.textview.account,
attributes, encrypted], attributes, encrypted],
self._update_img, [url, repl_start, repl_end, self._update_img, [weburl, repl_start, repl_end,
filepaths[0], encrypted]) filepaths[0], encrypted])
def _download_image(self, account, attributes, encrypted): def _download_image(self, account, attributes, encrypted):
@@ -516,6 +580,11 @@ class Base(object):
def on_open_menuitem_activate(self, menu, data): def on_open_menuitem_activate(self, menu, data):
filepath = data["filepath"] filepath = data["filepath"]
original_filename = data["original_filename"]
url = data["url"]
if original_filename.startswith('location_'):
helpers.launch_browser_mailer('url', url)
return
helpers.launch_file_manager(filepath) helpers.launch_file_manager(filepath)
def on_save_as_menuitem_activate(self, menu, data): def on_save_as_menuitem_activate(self, menu, data):