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 subprocess
import urllib
import urllib2
import webbrowser
import errno
import select
@ -42,6 +43,8 @@ import base64
import hashlib
import shlex
import caps_cache
import socket
import time
from encodings.punycode import punycode_encode
from string import Template
@ -58,6 +61,9 @@ try:
except Exception:
pass
import logging
log = logging.getLogger('gajim.c.helpers')
special_groups = (_('Transports'), _('Not in Roster'), _('Observers'), _('Groupchats'))
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
if gajim.HAVE_PYCURL:
import pycurl
from cStringIO import StringIO
def convert_bytes(string):
suffix = ''
@ -1425,4 +1434,112 @@ def get_proxy_info(account):
proxyptr = gajim.config.get_per('proxies', p)
for key in proxyptr.keys():
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 re
from cStringIO import StringIO
import socket
import time
import urllib2
import operator
@ -56,9 +54,6 @@ from common import gajim
from gtkgui_helpers import get_icon_pixmap
from common import helpers
if gajim.HAVE_PYCURL:
import pycurl
import tooltips
import logging
log = logging.getLogger('gajim.htmlview')
@ -494,118 +489,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
tag.title = title
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):
'''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))
@ -628,8 +513,9 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
update = True
else:
img_mark = self.textbuf.create_mark(None, self.iter, True)
gajim.thread_interface(self._get_img, [attrs], \
self._update_img, [attrs, img_mark])
gajim.thread_interface(helpers.download_image, [
self.conv_textview.account, attrs], self._update_img,
[attrs, img_mark])
alt = attrs.get('alt', '')
if alt:
alt += '\n'