From fcbf425309706f9ae9ce840f7c1393d25ee19da4 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 28 Feb 2018 13:57:43 +0100 Subject: [PATCH] [preview] Add map preview for locations provided by geo:-URIs --- url_image_preview/config_dialog.py | 11 ++ url_image_preview/url_image_preview.py | 141 ++++++++++++++++++------- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/url_image_preview/config_dialog.py b/url_image_preview/config_dialog.py index 0d56f7c..1cc8ae7 100644 --- a/url_image_preview/config_dialog.py +++ b/url_image_preview/config_dialog.py @@ -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'), diff --git a/url_image_preview/url_image_preview.py b/url_image_preview/url_image_preview.py index 48eb45c..ea0508b 100644 --- a/url_image_preview/url_image_preview.py +++ b/url_image_preview/url_image_preview.py @@ -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 + 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] + 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: + 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={}¢er={}&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):