Skip to content
Snippets Groups Projects
Commit 37169017 authored by Thilo Molitor's avatar Thilo Molitor
Browse files

[preview] Port to Gtk3

parent a4b62296
No related branches found
No related tags found
No related merge requests found
# simple redirect
from .url_image_preview import UrlImagePreviewPlugin
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
<requires lib="gtk+" version="3.0"/>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name Text -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">256 KiB</col>
</row>
<row>
<col id="0" translatable="yes">512 KiB</col>
</row>
<row>
<col id="0" translatable="yes">1 MiB</col>
</row>
<row>
<col id="0" translatable="yes">5 MiB</col>
</row>
<row>
<col id="0" translatable="yes">10 MiB</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore2">
<columns>
<!-- column-name Text -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">Open</col>
</row>
<row>
<col id="0" translatable="yes">Save as</col>
</row>
<row>
<col id="0" translatable="yes">Copy Link Location</col>
</row>
<row>
<col id="0" translatable="yes">Open Link in Browser</col>
</row>
<row>
<col id="0" translatable="yes">Open Downloaded File in Browser</col>
</row>
</data>
</object>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="can_focus">False</property>
<property name="border_width">9</property>
<child>
<object class="GtkHBox" id="hbox2">
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkLabel" id="preview_size_lebel">
<property name="width_request">133</property>
<property name="visible">True</property>
<property name="xalign">0.029999999329447746</property>
<property name="label" translatable="yes">Preview size</property>
<property name="ellipsize">start</property>
<property name="single_line_mode">True</property>
<property name="track_visited_links">False</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="preview_size">
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_tooltip">True</property>
<property name="tooltip_text" translatable="yes">Preview size(10-512)</property>
<property name="invisible_char">&#x25CF;</property>
<property name="width_chars">6</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
<signal name="value_changed" handler="preview_size_value_changed"/>
<property name="can_focus">False</property>
<property name="n_rows">3</property>
<property name="n_columns">2</property>
<child>
<object class="GtkSpinButton" id="preview_size">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="width_chars">6</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
<signal name="value-changed" handler="preview_size_value_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkComboBox" id="max_size_combobox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">liststore1</property>
<signal name="changed" handler="max_size_value_changed" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_EXPAND</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="leftclick_action_combobox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">liststore2</property>
<signal name="changed" handler="leftclick_action_changed" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_EXPAND</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="max_size_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">13</property>
<property name="label" translatable="yes">Accept files smaller then</property>
<property name="track_visited_links">False</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_EXPAND</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="preview_size_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Preview size</property>
<property name="track_visited_links">False</property>
</object>
<packing>
<property name="y_options">GTK_EXPAND</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="leftclick_action_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Left click action</property>
<property name="track_visited_links">False</property>
</object>
<packing>
<property name="y_options">GTK_EXPAND</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_EXPAND</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
......
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.0"/>
<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="stock">gtk-jump-to</property>
</object>
<object class="GtkImage" id="image5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-jump-to</property>
</object>
<object class="GtkMenu" id="context_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="open_menuitem">
<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="image">image1</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="save_as_menuitem">
<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="image">image2</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="encryption_separator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="copy_link_location_menuitem">
<property name="label" translatable="yes">_Copy Link Location</property>
<property name="visible">True</property>
<property name="can_focus">False</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>
</child>
<child>
<object class="GtkImageMenuItem" id="open_link_in_browser_menuitem">
<property name="label" translatable="yes">Open Link in _Browser</property>
<property name="visible">True</property>
<property name="can_focus">False</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>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="extras_separator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="open_file_in_browser_menuitem">
<property name="label" translatable="yes">Open _Downloaded File in Browser</property>
<property name="visible">True</property>
<property name="can_focus">False</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>
</child>
</object>
</interface>
# -*- coding: utf-8 -*-
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import urllib.request as urllib2
import socket
import re
from gajim.common import app
from gajim.common import helpers
import logging
import os
if os.name == 'nt':
import certifi
if app.HAVE_PYCURL:
import pycurl
from io import StringIO
log = logging.getLogger('gajim.plugin_system.url_image_preview.http_functions')
def get_http_head(account, url):
# Check if proxy is used
proxy = helpers.get_proxy_info(account)
if proxy and proxy['type'] in ('http', 'socks5'):
return _get_http_head_proxy(url, proxy)
return _get_http_head_direct(url)
def get_http_file(account, attrs):
# Check if proxy is used
proxy = helpers.get_proxy_info(account)
if proxy and proxy['type'] in ('http', 'socks5'):
return _get_http_proxy(attrs, proxy)
else:
return _get_http_direct(attrs)
def _get_http_head_direct(url):
log.debug('Head request direct for URL: %s' % url)
try:
req = urllib2.Request(url)
req.get_method = lambda: 'HEAD'
req.add_header('User-Agent', 'Gajim %s' % app.version)
if os.name == 'nt':
f = urllib2.urlopen(req, cafile=certifi.where())
else:
f = urllib2.urlopen(req)
except Exception as ex:
log.debug('Could not get head response for URL: %s' % url)
log.debug("%s" % str(ex))
return ('', 0)
ctype = f.headers['Content-Type']
clen = f.headers['Content-Length']
try:
clen = int(clen)
except ValueError:
pass
return (ctype, clen)
def _get_http_head_proxy(url, proxy):
log.debug('Head request with proxy for URL: %s' % url)
if not app.HAVE_PYCURL:
log.error('PYCURL not installed')
return ('', 0)
headers = ''
try:
b = StringIO()
c = pycurl.Curl()
c.setopt(pycurl.URL, url.encode('utf-8'))
c.setopt(pycurl.FOLLOWLOCATION, 1)
# Make a HEAD request:
c.setopt(pycurl.CUSTOMREQUEST, 'HEAD')
c.setopt(pycurl.NOBODY, 1)
c.setopt(pycurl.HEADER, 1)
c.setopt(pycurl.MAXFILESIZE, 2000000)
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.setopt(pycurl.USERAGENT, 'Gajim ' + app.version)
# set proxy
c.setopt(pycurl.PROXY, proxy['host'].encode('utf-8'))
c.setopt(pycurl.PROXYPORT, proxy['port'])
if proxy['useauth']:
c.setopt(pycurl.PROXYUSERPWD, proxy['user'].encode('utf-8') +
':' + proxy['pass'].encode('utf-8'))
c.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY)
if proxy['type'] == 'http':
c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_HTTP)
elif proxy['type'] == 'socks5':
c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5)
x = c.perform()
c.close()
headers = b.getvalue()
except pycurl.error as ex:
log.debug('Could not get head response for URL: %s' % url)
log.debug("%s" % str(ex))
return ('', 0)
ctype = ''
searchObj = re.search(r'^Content-Type: (.*)$', headers, re.M | re.I)
if searchObj:
ctype = searchObj.group(1).strip()
clen = 0
searchObj = re.search(r'^Content-Length: (.*)$', headers, re.M | re.I)
if searchObj:
try:
clen = int(searchObj.group(1).strip())
except ValueError:
pass
return (ctype, clen)
def _get_http_direct(attrs):
"""
Download a file. This function should
be launched in a separated thread.
"""
log.debug('Get request direct for URL: %s' % attrs['src'])
mem, alt, max_size = b'', '', 2 * 1024 * 1024
if 'max_size' in attrs:
max_size = attrs['max_size']
try:
req = urllib2.Request(attrs['src'])
req.add_header('User-Agent', 'Gajim ' + app.version)
if os.name == 'nt':
f = urllib2.urlopen(req, cafile=certifi.where())
else:
f = urllib2.urlopen(req)
except Exception as ex:
log.debug('Error loading file %s '
% attrs['src'] + str(ex))
pixbuf = None
alt = attrs.get('alt', 'Broken image')
else:
while True:
try:
temp = f.read(100)
except socket.timeout as ex:
log.debug('Timeout loading image %s '
% attrs['src'] + str(ex))
alt = attrs.get('alt', '')
if alt:
alt += '\n'
alt += _('Timeout loading image')
break
if temp:
mem += temp
else:
break
if len(mem) > max_size:
alt = attrs.get('alt', '')
if alt:
alt += '\n'
alt += _('Image is too big')
break
return (mem, alt)
def _get_http_proxy(attrs, proxy):
"""
Download an image through a proxy.
This function should be launched in a
separated thread.
"""
log.debug('Get request with proxy for URL: %s' % attrs['src'])
if not app.HAVE_PYCURL:
log.error('PYCURL not installed')
return '', _('PyCURL is not installed')
mem, alt, max_size = '', '', 2 * 1024 * 1024
if 'max_size' in attrs:
max_size = attrs['max_size']
try:
b = StringIO()
c = pycurl.Curl()
c.setopt(pycurl.URL, attrs['src'].encode('utf-8'))
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.MAXFILESIZE, max_size)
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.setopt(pycurl.USERAGENT, 'Gajim ' + app.version)
# set proxy
c.setopt(pycurl.PROXY, proxy['host'].encode('utf-8'))
c.setopt(pycurl.PROXYPORT, proxy['port'])
if proxy['useauth']:
c.setopt(pycurl.PROXYUSERPWD, proxy['user'].encode('utf-8') +
':' + proxy['pass'].encode('utf-8'))
c.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY)
if proxy['type'] == 'http':
c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_HTTP)
elif proxy['type'] == 'socks5':
c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5)
x = c.perform()
c.close()
t = b.getvalue()
return (t, attrs.get('alt', ''))
except pycurl.error as ex:
alt = attrs.get('alt', '')
if alt:
alt += '\n'
if ex[0] == pycurl.E_FILESIZE_EXCEEDED:
alt += _('Image is too big')
elif ex[0] == pycurl.E_OPERATION_TIMEOUTED:
alt += _('Timeout loading image')
else:
alt += _('Error loading image')
except Exception as ex:
log.debug('Error loading file %s ' % attrs['src'] + str(ex))
pixbuf = None
alt = attrs.get('alt', 'Broken image')
return ('', alt)
......@@ -2,8 +2,11 @@
name: Url image preview
short_name: url_image_preview
version: 0.5.6
description: Url image preview in chatbox.
description: Displays a preview of links to images
authors = Denis Fomin <fominde@gmail.com>
Yann Leboulanger <asterix@lagaule.org>
homepage = http://trac-plugins.gajim.org/wiki/UrlImagePreviewPlugin
Anders Sandblad <runeson@gmail.com>
Thilo Molitor <thilo@eightysoft.de>
Philipp Hoerist <philipp@hoerist.com>
homepage = https://dev.gajim.org/gajim/gajim-plugins/wikis/UrlImagePreviewPlugin
min_gajim_version: 0.16.11
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment