[preview] Cleanup code

This commit is contained in:
Daniel Brötzmann
2019-06-01 22:12:52 +02:00
committed by Philipp Hörist
parent 1a69014952
commit e73114c01e
5 changed files with 127 additions and 169 deletions

View File

@@ -91,8 +91,8 @@ class UrlImagePreviewConfigDialog(SettingsDialog):
] ]
SettingsDialog.__init__(self, parent, _('UrlImagePreview Configuration'), SettingsDialog.__init__(self, parent, _('UrlImagePreview Configuration'),
Gtk.DialogFlags.MODAL, settings, None, Gtk.DialogFlags.MODAL, settings, None,
extend=[ extend=[
('PreviewSizeSpinSetting', SizeSpinSetting)]) ('PreviewSizeSpinSetting', SizeSpinSetting)])
def on_setting(self, value, data): def on_setting(self, value, data):

View File

@@ -1,70 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 --> <!-- Generated with glade 3.22.1 -->
<interface> <interface>
<requires lib="gtk+" version="3.0"/> <requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-open</property>
</object>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save-as</property>
</object>
<object class="GtkImage" id="image3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-copy</property>
</object>
<object class="GtkImage" id="image4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-symbolic-link</property>
</object>
<object class="GtkImage" id="image5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-symbolic-link</property>
</object>
<object class="GtkImage" id="image6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">folder-download</property>
</object>
<object class="GtkMenu" id="context_menu"> <object class="GtkMenu" id="context_menu">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child> <child>
<object class="GtkImageMenuItem" id="open_menuitem"> <object class="GtkMenuItem" id="open_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Open</property> <property name="label" translatable="yes">_Open</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="image">image1</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkImageMenuItem" id="save_as_menuitem"> <object class="GtkMenuItem" id="save_as_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Save as</property> <property name="label" translatable="yes">_Save as</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="image">image2</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkImageMenuItem" id="open_folder_menuitem"> <object class="GtkMenuItem" id="open_folder_menuitem">
<property name="label" translatable="yes">Open _Folder</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Open _Folder</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="image">image6</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object> </object>
</child> </child>
<child> <child>
@@ -74,25 +35,19 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkImageMenuItem" id="copy_link_location_menuitem"> <object class="GtkMenuItem" id="copy_link_location_menuitem">
<property name="label" translatable="yes">_Copy Link Location</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">_Copy Link</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="image">image3</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkImageMenuItem" id="open_link_in_browser_menuitem"> <object class="GtkMenuItem" id="open_link_in_browser_menuitem">
<property name="label" translatable="yes">Open Link in _Browser</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Open Link in _Browser</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="image">image4</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object> </object>
</child> </child>
<child> <child>
@@ -102,14 +57,11 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkImageMenuItem" id="open_file_in_browser_menuitem"> <object class="GtkMenuItem" id="open_file_in_browser_menuitem">
<property name="label" translatable="yes">Open _Downloaded File in Browser</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Open _Downloaded File in Browser</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="image">image5</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object> </object>
</child> </child>
</object> </object>

View File

@@ -47,17 +47,17 @@ def _get_http_head_direct(url, verify):
context.check_hostname = False context.check_hostname = False
context.verify_mode = ssl.CERT_NONE context.verify_mode = ssl.CERT_NONE
log.warning('CERT Verification disabled') log.warning('CERT Verification disabled')
f = urllib2.urlopen(req, timeout=30, context=context) file_ = urllib2.urlopen(req, timeout=30, context=context)
else: else:
if os.name == 'nt': if os.name == 'nt':
f = urllib2.urlopen(req, cafile=certifi.where()) file_ = urllib2.urlopen(req, cafile=certifi.where())
else: else:
f = urllib2.urlopen(req) file_ = urllib2.urlopen(req)
except Exception as ex: except Exception as ex:
log.debug('Error', exc_info=True) log.debug('Error', exc_info=True)
return ('', 0) return ('', 0)
ctype = f.headers['Content-Type'] ctype = file_.headers['Content-Type']
clen = f.headers['Content-Length'] clen = file_.headers['Content-Length']
try: try:
clen = int(clen) clen = int(clen)
except (TypeError, ValueError): except (TypeError, ValueError):
@@ -65,10 +65,10 @@ def _get_http_head_direct(url, verify):
return (ctype, clen) return (ctype, clen)
def _get_http_direct(attrs): def _get_http_direct(attrs):
""" '''
Download a file. This function should Download a file. This function should
be launched in a separated thread. be launched in a separated thread.
""" '''
log.info('Get request direct for URL: %s', attrs['src']) log.info('Get request direct for URL: %s', attrs['src'])
mem, alt, max_size = b'', '', 2 * 1024 * 1024 mem, alt, max_size = b'', '', 2 * 1024 * 1024
if 'max_size' in attrs: if 'max_size' in attrs:
@@ -81,12 +81,12 @@ def _get_http_direct(attrs):
context.check_hostname = False context.check_hostname = False
context.verify_mode = ssl.CERT_NONE context.verify_mode = ssl.CERT_NONE
log.warning('CERT Verification disabled') log.warning('CERT Verification disabled')
f = urllib2.urlopen(req, timeout=30, context=context) file_ = urllib2.urlopen(req, timeout=30, context=context)
else: else:
if os.name == 'nt': if os.name == 'nt':
f = urllib2.urlopen(req, cafile=certifi.where()) file_ = urllib2.urlopen(req, cafile=certifi.where())
else: else:
f = urllib2.urlopen(req) file_ = urllib2.urlopen(req)
except Exception as ex: except Exception as ex:
log.debug('Error', exc_info=True) log.debug('Error', exc_info=True)
pixbuf = None pixbuf = None
@@ -94,7 +94,7 @@ def _get_http_direct(attrs):
else: else:
while True: while True:
try: try:
temp = f.read(100) temp = file_.read(100)
except socket.timeout as ex: except socket.timeout as ex:
log.debug('Timeout loading image %s', attrs['src'] + str(ex)) log.debug('Timeout loading image %s', attrs['src'] + str(ex))
alt = attrs.get('alt', '') alt = attrs.get('alt', '')

View File

@@ -17,11 +17,11 @@ def resize_gif(mem, path, resize_to):
def analyse_image(mem): def analyse_image(mem):
""" '''
Pre-process pass over the image to determine the mode (full or additive). Pre-process pass over the image to determine the mode (full or additive).
Necessary as assessing single frames isn't reliable. Need to know the mode Necessary as assessing single frames isn't reliable. Need to know the mode
before processing all frames. before processing all frames.
""" '''
image = Image.open(BytesIO(mem)) image = Image.open(BytesIO(mem))
results = { results = {
'size': image.size, 'size': image.size,

View File

@@ -20,11 +20,12 @@ import hashlib
import binascii import binascii
import logging import logging
import math import math
import shutil
from functools import partial
from urllib.parse import urlparse from urllib.parse import urlparse
from urllib.parse import unquote from urllib.parse import unquote
from io import BytesIO from io import BytesIO
import shutil
from functools import partial
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Gdk from gi.repository import Gdk
@@ -34,9 +35,10 @@ from gi.repository import GdkPixbuf
from gajim.common import app from gajim.common import app
from gajim.common import helpers from gajim.common import helpers
from gajim.common import configpaths from gajim.common import configpaths
from gajim.gtkgui_helpers import add_css_to_widget
from gajim import dialogs from gajim.gtk.dialogs import ErrorDialog
from gajim import gtkgui_helpers from gajim.gtk.filechoosers import FileSaveDialog
from gajim.gtk.util import get_cursor
from gajim.plugins import GajimPlugin from gajim.plugins import GajimPlugin
from gajim.plugins.helpers import log_calls from gajim.plugins.helpers import log_calls
@@ -46,9 +48,6 @@ from url_image_preview.http_functions import get_http_head
from url_image_preview.http_functions import get_http_file from url_image_preview.http_functions import get_http_file
from url_image_preview.config_dialog import UrlImagePreviewConfigDialog from url_image_preview.config_dialog import UrlImagePreviewConfigDialog
from gajim.gtk.filechoosers import FileSaveDialog
from gajim.gtk.util import get_cursor
log = logging.getLogger('gajim.p.preview') log = logging.getLogger('gajim.p.preview')
@@ -56,9 +55,9 @@ ERROR_MSG = None
try: try:
from PIL import Image from PIL import Image
from url_image_preview.resize_gif import resize_gif from url_image_preview.resize_gif import resize_gif
except: except ImportError:
log.debug('Pillow not available') log.debug('Pillow not available')
ERROR_MSG = 'Please install python-pillow' ERROR_MSG = _('Please install python-pillow')
try: try:
if os.name == 'nt': if os.name == 'nt':
@@ -70,8 +69,8 @@ try:
from cryptography.hazmat.primitives.ciphers.modes import GCM from cryptography.hazmat.primitives.ciphers.modes import GCM
decryption_available = True decryption_available = True
except Exception: except Exception:
DEP_MSG = 'For preview of encrypted images, ' \ DEP_MSG = _('To enable previews for encrypted images, '
'please install python-cryptography!' 'please install python-cryptography!')
log.exception('Error') log.exception('Error')
log.info('Decryption/Encryption disabled due to errors') log.info('Decryption/Encryption disabled due to errors')
decryption_available = False decryption_available = False
@@ -152,7 +151,7 @@ class UrlImagePreviewPlugin(GajimPlugin):
return return
class Base(object): class Base:
def __init__(self, plugin, textview): def __init__(self, plugin, textview):
self.plugin = plugin self.plugin = plugin
self.textview = textview self.textview = textview
@@ -167,11 +166,11 @@ class Base(object):
self._create_path(self.directory) self._create_path(self.directory)
self._create_path(self.thumbpath) self._create_path(self.thumbpath)
except Exception: except Exception:
log.error("Error creating download and/or thumbnail folder!") log.error('Error creating download and/or thumbnail folder!')
raise raise
def deinit_handlers(self): def deinit_handlers(self):
# remove all register handlers on wigets, created by self.xml # Remove all register handlers on wigets, created by self.xml
# to prevent circular references among objects # to prevent circular references among objects
for i in list(self.handlers.keys()): for i in list(self.handlers.keys()):
if self.handlers[i].handler_is_connected(i): if self.handlers[i].handler_is_connected(i):
@@ -182,7 +181,7 @@ class Base(object):
additional_data): additional_data):
if len(real_text.split(' ')) > 1: if len(real_text.split(' ')) > 1:
# urlparse dont recognises spaces as URL delimiter # urlparse doesn't recognise spaces as URL delimiter
log.debug('Url with text will not be displayed: %s', real_text) log.debug('Url with text will not be displayed: %s', real_text)
return return
@@ -200,8 +199,10 @@ class Base(object):
# Show URL, until image is loaded (if ever) # Show URL, until image is loaded (if ever)
ttt = buffer_.get_tag_table() ttt = buffer_.get_tag_table()
repl_start = buffer_.create_mark(None, iter_, True) repl_start = buffer_.create_mark(None, iter_, True)
buffer_.insert_with_tags(iter_, real_text, buffer_.insert_with_tags(
*[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]]) iter_,
real_text,
*[(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)
# Handle geo:-URIs # Handle geo:-URIs
@@ -221,11 +222,17 @@ class Base(object):
if lon == '': if lon == '':
return return
filename = 'location_' + geo_provider + '_' \ filename = 'location_%(provider)s_%(location)s' % {
+ location.replace(',', '_').replace('.', '-') 'provider': geo_provider,
'location': location.replace(',', '_').replace('.', '-')
}
newfilename = filename + ext newfilename = filename + ext
thumbfilename = filename + '_thumb_' \ thumbfilename = '%(filename)s_thumb_%(size)s%(ext)s' % {
+ str(self.plugin.config['PREVIEW_SIZE']) + ext 'filename': filename,
'size': str(self.plugin.config['PREVIEW_SIZE']),
'ext': 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]
@@ -264,9 +271,17 @@ class Base(object):
# so the filename should not exceed 90 # so the filename should not exceed 90
name = name[:90] name = name[:90]
namehash = hashlib.sha1(real_text.encode('utf-8')).hexdigest() namehash = hashlib.sha1(real_text.encode('utf-8')).hexdigest()
newfilename = name + '_' + namehash + ext newfilename = '%(name)s_%(namehash)s%(ext)s' % {
thumbfilename = name + '_' + namehash + '_thumb_' \ 'name': name,
+ str(self.plugin.config['PREVIEW_SIZE']) + ext 'namehash': namehash,
'ext': ext
}
thumbfilename = '%(name)s_%(namehash)s_thumb_%(size)s%(ext)s' % {
'name': name,
'namehash': namehash,
'size': str(self.plugin.config['PREVIEW_SIZE']),
'ext': 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)
@@ -287,19 +302,19 @@ class Base(object):
if len(key) == 32 and len(iv) == 12: if len(key) == 32 and len(iv) == 12:
encrypted = True encrypted = True
# 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': if urlparts.scheme == 'geo':
real_text = weburl real_text = weburl
with open(filepath, 'rb') as f: with open(filepath, 'rb') as file_to_preview:
mem = f.read() mem = file_to_preview.read()
app.thread_interface( app.thread_interface(
self._save_thumbnail, [thumbpath, mem], self._save_thumbnail, [thumbpath, mem],
self._update_img, [real_text, repl_start, self._update_img, [real_text, repl_start,
repl_end, filepath, encrypted]) repl_end, filepath, encrypted])
# display thumbnail if already downloadeded # Display thumbnail if already downloaded
# (but only if file also exists) # (but only if file 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': if urlparts.scheme == 'geo':
real_text = weburl real_text = weburl
@@ -308,7 +323,7 @@ class Base(object):
self._update_img, [real_text, repl_start, self._update_img, [real_text, repl_start,
repl_end, filepath, encrypted]) repl_end, filepath, encrypted])
# or download file, calculate thumbnail and finally display it # Or download file, calculate thumbnail, and finally display it
else: else:
if encrypted and not decryption_available: if encrypted and not decryption_available:
log.debug('Please install Crytography to decrypt pictures') log.debug('Please install Crytography to decrypt pictures')
@@ -327,7 +342,7 @@ class Base(object):
def _accept_uri(self, urlparts, real_text, additional_data): def _accept_uri(self, urlparts, real_text, additional_data):
try: try:
oob_url = additional_data["gajim"]["oob_url"] oob_url = additional_data['gajim']['oob_url']
except (KeyError, AttributeError): except (KeyError, AttributeError):
oob_url = None oob_url = None
@@ -336,7 +351,7 @@ class Base(object):
return False return False
# geo # geo
if urlparts.scheme == "geo": if urlparts.scheme == 'geo':
if self.plugin.config['GEO_PREVIEW_PROVIDER'] == 'no_preview': if self.plugin.config['GEO_PREVIEW_PROVIDER'] == 'no_preview':
log.info('geo: link preview is disabled') log.info('geo: link preview is disabled')
return False return False
@@ -353,7 +368,7 @@ class Base(object):
log.info('Incorrect oob data found') log.info('Incorrect oob data found')
return False return False
log.info('Not supported URI scheme found: %s', real_text) log.info('Unsupported URI scheme found: %s', real_text)
return False return False
def _save_thumbnail(self, thumbpath, mem): def _save_thumbnail(self, thumbpath, mem):
@@ -372,7 +387,7 @@ class Base(object):
log.debug(error) log.debug(error)
# Try Pillow # Try Pillow
image = Image.open(BytesIO(mem)).convert("RGBA") image = Image.open(BytesIO(mem)).convert('RGBA')
array = GLib.Bytes.new(image.tobytes()) array = GLib.Bytes.new(image.tobytes())
width, height = image.size width, height = image.size
pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(
@@ -430,30 +445,20 @@ class Base(object):
@staticmethod @staticmethod
def _write_file(path, data): def _write_file(path, data):
log.info("Writing '%s' of size %d...", path, len(data)) log.info('Writing \'%s\' of size %d...', path, len(data))
try: try:
with open(path, "wb") as output_file: with open(path, 'wb') as output_file:
output_file.write(data) output_file.write(data)
output_file.closed output_file.closed
except Exception as e: except Exception as e:
log.error("Failed to write file '%s'!", path) log.error('Failed to write file \'%s\'!', path)
raise raise
def _get_at_end(self): def _get_at_end(self):
try: return self.textview.autoscroll
# Gajim 1.0.0
return self.textview.at_the_end()
except AttributeError:
# Gajim 1.0.1
return self.textview.autoscroll
def _scroll_to_end(self): def _scroll_to_end(self):
try: self.textview.scroll_to_end()
# Gajim 1.0.0
self.textview.scroll_to_end_iter()
except AttributeError:
# Gajim 1.0.1
self.textview.scroll_to_end()
def _update_img(self, pixbuf, url, repl_start, repl_end, def _update_img(self, pixbuf, url, repl_start, repl_end,
filepath, encrypted): filepath, encrypted):
@@ -473,7 +478,7 @@ class Base(object):
buffer_ = repl_start.get_buffer() buffer_ = repl_start.get_buffer()
iter_ = buffer_.get_iter_at_mark(repl_start) iter_ = buffer_.get_iter_at_mark(repl_start)
buffer_.insert(iter_, "\n") buffer_.insert(iter_, '\n')
anchor = buffer_.create_child_anchor(iter_) anchor = buffer_.create_child_anchor(iter_)
anchor.plaintext = url anchor.plaintext = url
@@ -491,9 +496,9 @@ class Base(object):
if at_end: if at_end:
self._scroll_to_end() self._scroll_to_end()
except Exception as ex: except Exception as ex:
log.exception("Exception while loading %s: %s", url, ex) log.exception('Exception while loading %s: %s', url, ex)
return False return False
# add to mainloop --> make call threadsafe # Add to mainloop --> make call threadsafe
GLib.idle_add(add_to_textview) GLib.idle_add(add_to_textview)
def _create_clickable_image(self, pixbuf, url): def _create_clickable_image(self, pixbuf, url):
@@ -505,7 +510,7 @@ class Base(object):
css = '''#Preview { css = '''#Preview {
box-shadow: 0px 0px 3px 0px alpha(@theme_text_color, 0.2); box-shadow: 0px 0px 3px 0px alpha(@theme_text_color, 0.2);
margin: 5px 10px 5px 10px; }''' margin: 5px 10px 5px 10px; }'''
gtkgui_helpers.add_css_to_widget(image, css) add_css_to_widget(image, css)
image.set_name('Preview') image.set_name('Preview')
event_box = Gtk.EventBox() event_box = Gtk.EventBox()
@@ -520,19 +525,19 @@ class Base(object):
file_mime, file_size = tuple_arg file_mime, file_size = tuple_arg
# Check if mime type is acceptable # Check if mime type is acceptable
if not file_mime or not file_size: if not file_mime or not file_size:
log.info("Failed to load HEAD Request for URL: '%s' " log.info('Failed to load HEAD Request for URL: \'%s\' '
"mime: %s, size: %s", url, file_mime, file_size) 'mime: %s, size: %s', url, file_mime, file_size)
# URL is already displayed # URL is already displayed
return return
if file_mime.lower() not in ACCEPTED_MIME_TYPES: if file_mime.lower() not in ACCEPTED_MIME_TYPES:
log.info("Not accepted mime type '%s' for URL: '%s'", log.info('Not accepted mime type \'%s\' for URL: \'%s\'',
file_mime.lower(), url) file_mime.lower(), url)
# URL is already displayed # URL is already displayed
return return
# Check if file size is acceptable # Check if file size is acceptable
max_size = int(self.plugin.config['MAX_FILE_SIZE']) max_size = int(self.plugin.config['MAX_FILE_SIZE'])
if file_size > max_size or file_size == 0: if file_size > max_size or file_size == 0:
log.info("File size (%s) too big or unknown (zero) for URL: '%s'", log.info('File size (%s) too big or unknown (zero) for URL: \'%s\'',
file_size, url) file_size, url)
# URL is already displayed # URL is already displayed
return return
@@ -572,17 +577,17 @@ class Base(object):
' (see error log for more information)')) ' (see error log for more information)'))
log.error(str(e)) log.error(str(e))
# Create thumbnail, write it to harddisk and return it # Create thumbnail, write to disk and return it
return self._save_thumbnail(thumbpath, mem) return self._save_thumbnail(thumbpath, mem)
def _create_path(self, folder): def _create_path(self, folder):
if os.path.exists(folder): if os.path.exists(folder):
return return
log.debug("creating folder '%s'" % folder) log.debug('Creating folder \'%s\'' % folder)
os.mkdir(folder, 0o700) os.mkdir(folder, 0o700)
def _aes_decrypt_fast(self, key, iv, payload): def _aes_decrypt_fast(self, key, iv, payload):
# Use AES128 GCM with the given key and iv to decrypt the payload. # Use AES128 GCM with the given key and iv to decrypt the payload
if os.name == 'nt': if os.name == 'nt':
be = backend be = backend
else: else:
@@ -612,7 +617,7 @@ class Base(object):
'open_file_in_browser_menuitem') 'open_file_in_browser_menuitem')
extras_separator = xml.get_object('extras_separator') extras_separator = xml.get_object('extras_separator')
if data["encrypted"]: if data['encrypted']:
open_link_in_browser_menuitem.hide() open_link_in_browser_menuitem.hide()
if app.config.get('autodetect_browser_mailer') \ if app.config.get('autodetect_browser_mailer') \
or app.config.get('custombrowser') == '': or app.config.get('custombrowser') == '':
@@ -641,25 +646,26 @@ class Base(object):
return menu return menu
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"] original_filename = data['original_filename']
url = data["url"] url = data['url']
if original_filename.startswith('location_'): if original_filename.startswith('location_'):
helpers.open_uri(url) helpers.open_uri(url)
return 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):
filepath = data["filepath"] filepath = data['filepath']
original_filename = data["original_filename"] original_filename = data['original_filename']
def on_ok(target_path): def on_ok(target_path):
dirname = os.path.dirname(target_path) dirname = os.path.dirname(target_path)
if not os.access(dirname, os.W_OK): if not os.access(dirname, os.W_OK):
dialogs.ErrorDialog( ErrorDialog(
_('Directory "%s" is not writable') % dirname, _('Directory \'%s\' is not writable') % dirname,
_('You do not have permission to ' _('You do not have the proper permissions to '
'create files in this directory.')) 'create files in this directory.'),
transient_for=app.app.get_active_window())
return return
shutil.copy(filepath, target_path) shutil.copy(filepath, target_path)
@@ -672,29 +678,29 @@ class Base(object):
helpers.launch_file_manager(self.directory) helpers.launch_file_manager(self.directory)
def _on_copy_link_location_menuitem_activate(self, menu, data): def _on_copy_link_location_menuitem_activate(self, menu, data):
url = data["url"] url = data['url']
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clipboard.set_text(url, -1) clipboard.set_text(url, -1)
clipboard.store() clipboard.store()
def _on_open_link_in_browser_menuitem_activate(self, menu, data): def _on_open_link_in_browser_menuitem_activate(self, menu, data):
url = data["url"] url = data['url']
if data["encrypted"]: if data['encrypted']:
self._on_open_menuitem_activate(self, data) self._on_open_menuitem_activate(self, data)
else: else:
helpers.open_uri(url) helpers.open_uri(url)
def _on_open_file_in_browser_menuitem_activate(self, menu, data): def _on_open_file_in_browser_menuitem_activate(self, menu, data):
if os.name == "nt": if os.name == 'nt':
filepath = "file://" + os.path.abspath(data["filepath"]) filepath = 'file://' + os.path.abspath(data['filepath'])
else: else:
filepath = "file://" + data["filepath"] filepath = 'file://' + data['filepath']
if app.config.get('autodetect_browser_mailer') \ if app.config.get('autodetect_browser_mailer') \
or app.config.get('custombrowser') == '': or app.config.get('custombrowser') == '':
dialogs.ErrorDialog( ErrorDialog(
_('Cannot open downloaded file in browser'), _('Cannot open downloaded file in browser'),
_('You have to set a custom browser executable ' _('You have to set a custom browser executable '
'in your gajim settings for this to work.'), 'in Gajim\'s Preferences for this to work.'),
transient_for=app.app.get_active_window()) transient_for=app.app.get_active_window())
return return
command = app.config.get('custombrowser') command = app.config.get('custombrowser')
@@ -706,17 +712,17 @@ class Base(object):
def _on_button_press_event(self, eb, event, filepath, original_filename, def _on_button_press_event(self, eb, event, filepath, original_filename,
url, encrypted): url, encrypted):
data = {"filepath": filepath, data = {'filepath': filepath,
"original_filename": original_filename, 'original_filename': original_filename,
"url": url, 'url': url,
"encrypted": encrypted} 'encrypted': encrypted}
# left click # Left click
if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 1: if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 1:
method = getattr(self, "_on_" method = getattr(self, '_on_'
+ self.plugin.config['LEFTCLICK_ACTION'] + self.plugin.config['LEFTCLICK_ACTION']
+ "_activate") + '_activate')
method(event, data) method(event, data)
# right klick # Right klick
elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3: elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
menu = self.make_rightclick_menu(event, data) menu = self.make_rightclick_menu(event, data)
# menu.attach_to_widget(self.tv, None) # menu.attach_to_widget(self.tv, None)
@@ -726,9 +732,9 @@ class Base(object):
@staticmethod @staticmethod
def _raise_error_dialog(pritext, sectext): def _raise_error_dialog(pritext, sectext):
# Used by methods that run in a different thread # Used by methods that run in a different thread
dialogs.ErrorDialog(pritext, ErrorDialog(pritext,
sectext, sectext,
transient_for=app.app.get_active_window()) transient_for=app.app.get_active_window())
def disconnect_from_chat_control(self): def disconnect_from_chat_control(self):
pass pass