move functions to download an image from htmltextview.py to helpers.py

This commit is contained in:
Yann Leboulanger 2011-11-14 23:23:40 +01:00
parent b28b3d4ed3
commit 3c294252f0
2 changed files with 122 additions and 119 deletions

View file

@ -35,6 +35,7 @@ import locale
import os import os
import subprocess import subprocess
import urllib import urllib
import urllib2
import webbrowser import webbrowser
import errno import errno
import select import select
@ -42,6 +43,8 @@ import base64
import hashlib import hashlib
import shlex import shlex
import caps_cache import caps_cache
import socket
import time
from encodings.punycode import punycode_encode from encodings.punycode import punycode_encode
from string import Template from string import Template
@ -58,6 +61,9 @@ try:
except Exception: except Exception:
pass pass
import logging
log = logging.getLogger('gajim.c.helpers')
special_groups = (_('Transports'), _('Not in Roster'), _('Observers'), _('Groupchats')) special_groups = (_('Transports'), _('Not in Roster'), _('Observers'), _('Groupchats'))
class InvalidFormat(Exception): class InvalidFormat(Exception):
@ -620,6 +626,9 @@ def datetime_tuple(timestamp):
# import gajim only when needed (after decode_string is defined) see #4764 # import gajim only when needed (after decode_string is defined) see #4764
import gajim import gajim
if gajim.HAVE_PYCURL:
import pycurl
from cStringIO import StringIO
def convert_bytes(string): def convert_bytes(string):
suffix = '' suffix = ''
@ -1426,3 +1435,111 @@ def get_proxy_info(account):
for key in proxyptr.keys(): for key in proxyptr.keys():
proxy[key] = proxyptr[key][1] proxy[key] = proxyptr[key][1]
return proxy return proxy
def _get_img_direct(attrs):
"""
Download an image. This function should be launched in a separated thread.
"""
mem, alt = '', ''
# Wait maximum 5s for connection
socket.setdefaulttimeout(5)
try:
req = urllib2.Request(attrs['src'])
req.add_header('User-Agent', 'Gajim ' + gajim.version)
f = urllib2.urlopen(req)
except Exception, ex:
log.debug('Error loading image %s ' % attrs['src'] + str(ex))
pixbuf = None
alt = attrs.get('alt', 'Broken image')
else:
# Wait 0.5s between each byte
try:
f.fp._sock.fp._sock.settimeout(0.5)
except Exception:
pass
# Max image size = 2 MB (to try to prevent DoS)
deadline = time.time() + 3
while True:
if time.time() > deadline:
log.debug('Timeout loading image %s ' % attrs['src'] + str(ex))
mem = ''
alt = attrs.get('alt', '')
if alt:
alt += '\n'
alt += _('Timeout loading image')
break
try:
temp = f.read(100)
except socket.timeout, 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) > 2*1024*1024:
alt = attrs.get('alt', '')
if alt:
alt += '\n'
alt += _('Image is too big')
break
return (mem, alt)
def _get_img_proxy(attrs, proxy):
"""
Download an image through a proxy. This function should be launched in a
separated thread.
"""
if not gajim.HAVE_PYCURL:
return '', _('PyCURL is not installed')
mem, alt = '', ''
try:
b = StringIO()
c = pycurl.Curl()
c.setopt(pycurl.URL, attrs['src'].encode('utf-8'))
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.CONNECTTIMEOUT, 5)
c.setopt(pycurl.TIMEOUT, 10)
c.setopt(pycurl.MAXFILESIZE, 2000000)
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.setopt(pycurl.USERAGENT, 'Gajim ' + gajim.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, 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, ex:
log.debug('Error loading image %s ' % attrs['src'] + str(ex))
pixbuf = None
alt = attrs.get('alt', 'Broken image')
return ('', alt)
def download_image(account, attrs):
proxy = get_proxy_info(account)
if proxy and proxy['type'] in ('http', 'socks5'):
return _get_img_proxy(attrs, proxy)
return _get_img_direct(attrs)

View file

@ -41,8 +41,6 @@ import gtk
import xml.sax, xml.sax.handler import xml.sax, xml.sax.handler
import re import re
from cStringIO import StringIO from cStringIO import StringIO
import socket
import time
import urllib2 import urllib2
import operator import operator
@ -56,9 +54,6 @@ from common import gajim
from gtkgui_helpers import get_icon_pixmap from gtkgui_helpers import get_icon_pixmap
from common import helpers from common import helpers
if gajim.HAVE_PYCURL:
import pycurl
import tooltips import tooltips
import logging import logging
log = logging.getLogger('gajim.htmlview') log = logging.getLogger('gajim.htmlview')
@ -494,118 +489,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
tag.title = title tag.title = title
return tag return tag
def _get_img_direct(self, attrs):
"""
Download an image. This function is launched in a separate thread.
"""
mem, alt = '', ''
# Wait maximum 5s for connection
socket.setdefaulttimeout(5)
try:
req = urllib2.Request(attrs['src'])
req.add_header('User-Agent', 'Gajim ' + gajim.version)
f = urllib2.urlopen(req)
except Exception, ex:
log.debug('Error loading image %s ' % attrs['src'] + str(ex))
pixbuf = None
alt = attrs.get('alt', 'Broken image')
else:
# Wait 0.5s between each byte
try:
f.fp._sock.fp._sock.settimeout(0.5)
except Exception:
pass
# Max image size = 2 MB (to try to prevent DoS)
deadline = time.time() + 3
while True:
if time.time() > deadline:
log.debug(str('Timeout loading image %s ' % \
attrs['src'] + ex))
mem = ''
alt = attrs.get('alt', '')
if alt:
alt += '\n'
alt += _('Timeout loading image')
break
try:
temp = f.read(100)
except socket.timeout, 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) > 2*1024*1024:
alt = attrs.get('alt', '')
if alt:
alt += '\n'
alt += _('Image is too big')
break
return (mem, alt)
def _get_img_proxy(self, attrs, proxy):
"""
Download an image through a proxy. This function is launched in a
separate thread.
"""
if not gajim.HAVE_PYCURL:
return '', _('PyCURL is not installed')
mem, alt = '', ''
try:
b = StringIO()
c = pycurl.Curl()
c.setopt(pycurl.URL, attrs['src'].encode('utf-8'))
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.CONNECTTIMEOUT, 5)
c.setopt(pycurl.TIMEOUT, 10)
c.setopt(pycurl.MAXFILESIZE, 2000000)
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.setopt(pycurl.USERAGENT, 'Gajim ' + gajim.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, 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, ex:
log.debug('Error loading image %s ' % attrs['src'] + str(ex))
pixbuf = None
alt = attrs.get('alt', 'Broken image')
return ('', alt)
def _get_img(self, attrs):
proxy = helpers.get_proxy_info(self.conv_textview.account)
if proxy and proxy['type'] in ('http', 'socks5'):
return self._get_img_proxy(attrs, proxy)
return self._get_img_direct(attrs)
def _update_img(self, (mem, alt), attrs, img_mark): def _update_img(self, (mem, alt), attrs, img_mark):
'''Callback function called after the function _get_img above. '''Callback function called after the function helpers.download_image.
''' '''
self._process_img(attrs, (mem, alt, img_mark)) self._process_img(attrs, (mem, alt, img_mark))
@ -628,8 +513,9 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
update = True update = True
else: else:
img_mark = self.textbuf.create_mark(None, self.iter, True) img_mark = self.textbuf.create_mark(None, self.iter, True)
gajim.thread_interface(self._get_img, [attrs], \ gajim.thread_interface(helpers.download_image, [
self._update_img, [attrs, img_mark]) self.conv_textview.account, attrs], self._update_img,
[attrs, img_mark])
alt = attrs.get('alt', '') alt = attrs.get('alt', '')
if alt: if alt:
alt += '\n' alt += '\n'