Commit fcbf4253 authored by Daniel Brötzmann's avatar Daniel Brötzmann Committed by Philipp Hörist

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

parent cfc13d01
......@@ -39,6 +39,11 @@ class UrlImagePreviewConfigDialog(OptionsDialog):
(_('Open Link in Browser'), 'open_link_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
options = [
Option('PreviewSizeSpinOption', _('Preview size'),
......@@ -58,6 +63,12 @@ class UrlImagePreviewConfigDialog(OptionsDialog):
props={'items': actions,
'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'),
OptionType.VALUE, self.plugin.config['VERIFY'],
callback=self.on_option, data='VERIFY'),
......
......@@ -83,6 +83,7 @@ class UrlImagePreviewPlugin(GajimPlugin):
'MAX_FILE_SIZE': (524288, 'Max file size for image preview'),
'LEFTCLICK_ACTION': ('open_menuitem', 'Open'),
'ANONYMOUS_MUC': (False, ''),
'GEO_PREVIEW_PROVIDER': ('Google', 'Google Maps'),
'VERIFY': (True, ''),}
self.controls = {}
self.history_window_control = None
......@@ -161,11 +162,14 @@ class Base(object):
def print_real_text(self, real_text, text_tags, graphics, iter_,
additional_data):
urlparts = urlparse(real_text)
if (urlparts.scheme not in ["https", "aesgcm"] or
not urlparts.netloc):
log.info("Not accepting URL scheme '%s' for image preview: %s",
urlparts.scheme, real_text)
return
if urlparts.scheme == "geo":
if self.plugin.config['GEO_PREVIEW_PROVIDER'] == 'no_preview':
return
elif (urlparts.scheme not in ["https", "aesgcm"] or not urlparts.netloc):
if urlparts.scheme != "geo":
log.info("Not accepting URL scheme '%s' for image preview: %s",
urlparts.scheme, real_text)
return
try:
oob_url = additional_data["gajim"]["oob_url"]
......@@ -175,10 +179,11 @@ class Base(object):
# allow aesgcm uris without oob marker (aesgcm uris are always
# httpupload filetransfers)
if urlparts.scheme != "aesgcm" and real_text != oob_url:
log.info("Not accepting URL for image preview "
"(wrong or no oob data): %s", real_text)
log.debug("additional_data: %s", additional_data)
return
if urlparts.scheme != "geo":
log.info("Not accepting URL for image preview "
"(wrong or no oob data): %s", real_text)
log.debug("additional_data: %s", additional_data)
return
# Don't print the URL in the message window (in the calling function)
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"]])
repl_end = buffer_.create_mark(None, iter_, True)
filename = os.path.basename(urlparts.path)
ext = os.path.splitext(filename)[1]
name = os.path.splitext(filename)[0]
namehash = hashlib.sha1(real_text.encode('utf-8')).hexdigest()
newfilename = name + '_' + namehash + ext
thumbfilename = name + '_' + namehash + '_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]
key = ''
iv = ''
encrypted = False
if urlparts.fragment:
fragment = binascii.unhexlify(urlparts.fragment)
key = fragment[16:]
iv = fragment[: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:
if not real_text.startswith('geo:'):
weburl = real_text
filename = os.path.basename(urlparts.path)
ext = os.path.splitext(filename)[1]
name = os.path.splitext(filename)[0]
namehash = hashlib.sha1(real_text.encode('utf-8')).hexdigest()
newfilename = name + '_' + namehash + ext
thumbfilename = name + '_' + namehash + '_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]
key = ''
iv = ''
encrypted = False
if urlparts.fragment:
fragment = binascii.unhexlify(urlparts.fragment)
key = fragment[16:]
iv = fragment[: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
# 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
if os.path.exists(filepath) and not os.path.exists(thumbpath):
if urlparts.scheme == 'geo':
real_text = weburl
with open(filepath, 'rb') as f:
mem = f.read()
app.thread_interface(
......@@ -233,6 +291,8 @@ class Base(object):
# display thumbnail if already downloadeded
# (but only if file also exists)
elif os.path.exists(filepath) and os.path.exists(thumbpath):
if urlparts.scheme == 'geo':
real_text = weburl
app.thread_interface(
self._load_thumbnail, [thumbpath],
self._update_img, [real_text, repl_start,
......@@ -251,8 +311,9 @@ class Base(object):
verify = self.plugin.config['VERIFY']
app.thread_interface(
get_http_head, [self.textview.account, real_text, verify],
self._check_mime_size, [real_text, repl_start, repl_end,
filepaths, key, iv, encrypted])
self._check_mime_size, [real_text, weburl, repl_start,
repl_end, filepaths, key, iv,
encrypted])
def _save_thumbnail(self, thumbpath, mem):
size = self.plugin.config['PREVIEW_SIZE']
......@@ -349,6 +410,9 @@ class Base(object):
urlparts = urlparse(url)
filename = os.path.basename(urlparts.path)
if os.path.basename(filepath).startswith('location_'):
filename = os.path.basename(filepath)
event_box = Gtk.EventBox()
event_box.connect('button-press-event', self.on_button_press_event,
filepath, filename, url, encrypted)
......@@ -392,7 +456,7 @@ class Base(object):
GLib.idle_add(add_to_textview)
def _check_mime_size(self, tuple_arg,
url, repl_start, repl_end, filepaths,
url, weburl, repl_start, repl_end, filepaths,
key, iv, encrypted):
file_mime, file_size = tuple_arg
# Check if mime type is acceptable
......@@ -424,7 +488,7 @@ class Base(object):
app.thread_interface(
self._download_image, [self.textview.account,
attributes, encrypted],
self._update_img, [url, repl_start, repl_end,
self._update_img, [weburl, repl_start, repl_end,
filepaths[0], encrypted])
def _download_image(self, account, attributes, encrypted):
......@@ -516,6 +580,11 @@ class Base(object):
def on_open_menuitem_activate(self, menu, data):
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)
def on_save_as_menuitem_activate(self, menu, data):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment