[preview] Add map preview for locations provided by geo:-URIs
This commit is contained in:
@@ -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'),
|
||||||
|
|||||||
@@ -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={}¢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
|
# 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):
|
||||||
|
|||||||
Reference in New Issue
Block a user