def print_special_text(self, special_text, other_tags, graphics=True,
    iter_=None):
        if not self.plugin.active:
            return
        is_xhtml_link = None
        text_is_valid_uri = False
        buffer_ = self.textview.tv.get_buffer()

        # Detect XHTML-IM link
        ttt = buffer_.get_tag_table()
        tags_ = [(ttt.lookup(t) if isinstance(t, str) else t) for t in other_tags]
        for t in tags_:
            is_xhtml_link = getattr(t, 'href', None)
            if is_xhtml_link:
                break
        # Check if we accept this as an uri
        schemes = gajim.config.get('uri_schemes').split()
        for scheme in schemes:
            if special_text.startswith(scheme):
                text_is_valid_uri = True
        if special_text.startswith('www.') or special_text.startswith('ftp.') \
        or text_is_valid_uri and not is_xhtml_link:
            if len(special_text) < self.plugin.config['IN_MAX_CHARS']:
                return
            end_iter = buffer_.get_end_iter()
            mark = buffer_.create_mark(None, end_iter, True)
            gajim.thread_interface(self.insert_hyperlink, [mark, special_text,
                ttt])
            self.textview.plugin_modified = True
Example #2
0
    def print_special_text(self, tv, special_text, other_tags, graphics=True,
                           iter_=None):
        conv_textview = tv
        textview = tv.tv
        # geo:48.2057365,16.3435941
        if not special_text.startswith('geo:'):
            return

        buffer_ = textview.get_buffer()
        if not iter_:
            iter_ = buffer_.get_end_iter()

        # Show URL, until image is loaded (if ever)
        ttt = buffer_.get_tag_table()
        repl_start = buffer_.create_mark(None, iter_, True)
        buffer_.insert_with_tags(iter_, special_text,
            *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
        repl_end = buffer_.create_mark(None, iter_, True)

        zoom = 17
        size = 200
        color = 'blue'

        coordinates = special_text.split(':')[1]

        lat = coordinates.split(',')[0]
        lon = coordinates.split(',')[1]

        if not (len(lat) == 10 and len(lon) == 10):
            return

        filename = coordinates.replace(',', '_').replace('.', '-')
        filepath = os.path.join(self.thumbpath, filename)

        url = 'https://maps.googleapis.com/maps/api/staticmap?center={}' \
              '&zoom={}&size={}x{}&markers=color:{}' \
              '|label:S|{}'.format(coordinates, zoom, size, size,
                                   color, coordinates)

        weburl = 'https://www.google.at/maps/place/{}'.format(coordinates)

        log.debug(url)

        if os.path.exists(filepath):
            gajim.thread_interface(
                self.load_thumbnail, [filepath],
                self.updatechat, [weburl, repl_start, repl_end, textview])
        else:
            gajim.thread_interface(
                self.download, [url, filepath],
                self.updatechat, [weburl, repl_start, repl_end, textview])

        # Don't print the URL in the message window (in the calling function)
        conv_textview.plugin_modified = True
Example #3
0
    def print_special_text(self,
                           special_text,
                           other_tags,
                           graphics=True,
                           iter_=None):
        # remove qip bbcode
        special_text = special_text.rsplit('[/img]')[0]

        if special_text.startswith('www.'):
            special_text = 'http://' + special_text
        if special_text.startswith('ftp.'):
            special_text = 'ftp://' + special_text

        parts = urlparse(special_text)
        if parts.scheme not in ["https", "http", "ftp", "ftps"] or \
                not parts.netloc:
            log.info("Not accepting URL for image preview: %s" % special_text)
            return

        buffer_ = self.textview.tv.get_buffer()
        if not iter_:
            iter_ = buffer_.get_end_iter()

        # Detect XHTML-IM link
        ttt = buffer_.get_tag_table()
        tags_ = [(ttt.lookup(t) if isinstance(t, str) else t)
                 for t in other_tags]
        for t in tags_:
            is_xhtml_link = getattr(t, 'href', None)
            if is_xhtml_link:
                break

        # Show URL, until image is loaded (if ever)
        repl_start = buffer_.create_mark(None, iter_, True)
        buffer_.insert_with_tags(iter_, special_text, \
            *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
        repl_end = buffer_.create_mark(None, iter_, True)

        # First get the http head request with does not fetch data, just headers
        gajim.thread_interface(self._get_http_head,
                               [self.textview.account, special_text],
                               self._check_mime_size,
                               [special_text, repl_start, repl_end])

        # Don't print the URL in the message window (in the calling function)
        self.textview.plugin_modified = True
Example #4
0
    def _process_img(self, attrs, loaded=None):
        '''Process a img tag.
        '''
        mem = ''
        update = False
        pixbuf = None
        replace_mark = None
        replace_tags = None

        try:
            if attrs['src'].startswith('data:image/'):
                # The "data" URL scheme http://tools.ietf.org/html/rfc2397
                import base64
                img = attrs['src'].split(',')[1]
                mem = base64.standard_b64decode(
                    urllib.parse.unquote(img).encode('utf-8'))
            elif loaded is not None:
                (mem, alt, replace_mark, replace_tags) = loaded
                update = True
            else:
                if self.conv_textview:
                    img_mark = self.textbuf.create_mark(None, self.iter, True)
                    gajim.thread_interface(
                        helpers.download_image,
                        [self.conv_textview.account, attrs], self._update_img,
                        [attrs, img_mark,
                         self._get_style_tags()])
                    alt = attrs.get('alt', '')
                    if alt:
                        alt += '\n'
                    alt += _('Loading')
                    pixbuf = get_icon_pixmap('gtk-no')
            if mem:
                # Caveat: GdkPixbuf is known not to be safe to load
                # images from network... this program is now potentially
                # hackable ;)
                loader = GdkPixbuf.PixbufLoader()
                dims = [0, 0]

                def height_cb(length):
                    dims[1] = length

                def width_cb(length):
                    dims[0] = length

                # process width and height attributes
                w = attrs.get('width')
                h = attrs.get('height')
                # override with width and height styles
                for attr, val in style_iter(attrs.get('style', '')):
                    if attr == 'width':
                        w = val
                    elif attr == 'height':
                        h = val
                if w:
                    self._parse_length(w, False, False, 1, 1000, width_cb)
                if h:
                    self._parse_length(h, False, False, 1, 1000, height_cb)

                def set_size(pixbuf, w, h, dims):
                    """
                    FIXME: Floats should be relative to the whole textview, and
                    resize with it. This needs new pifbufs for every resize,
                    GdkPixbuf.Pixbuf.scale_simple or similar.
                    """
                    if isinstance(dims[0], float):
                        dims[0] = int(dims[0] * w)
                    elif not dims[0]:
                        dims[0] = w
                    if isinstance(dims[1], float):
                        dims[1] = int(dims[1] * h)
                    if not dims[1]:
                        dims[1] = h
                    loader.set_size(*dims)

                if w or h:
                    loader.connect('size-prepared', set_size, dims)
                loader.write(mem)
                loader.close()
                pixbuf = loader.get_pixbuf()
                alt = attrs.get('alt', '')
            working_iter = self.iter
            if replace_mark is not None:
                working_iter = self.textbuf.get_iter_at_mark(replace_mark)
                next_iter = working_iter.copy()
                next_iter.forward_char()
                self.textbuf.delete(working_iter, next_iter)
                self.textbuf.delete_mark(replace_mark)
            if pixbuf is not None:
                if replace_mark:
                    tags = replace_tags
                else:
                    tags = self._get_style_tags()
                if tags:
                    tmpmark = self.textbuf.create_mark(None, working_iter,
                                                       True)
                self.textbuf.insert_pixbuf(working_iter, pixbuf)
                self.starting = False
                if tags:
                    start = self.textbuf.get_iter_at_mark(tmpmark)
                    for tag in tags:
                        self.textbuf.apply_tag(tag, start, working_iter)
                    self.textbuf.delete_mark(tmpmark)
            else:
                self._insert_text('[IMG: %s]' % alt, working_iter)
        except Exception as ex:
            log.error('Error loading image ' + str(ex))
            pixbuf = None
            alt = attrs.get('alt', 'Broken image')
            try:
                loader.close()
            except Exception:
                pass
        return pixbuf
Example #5
0
 def print_special_text(self, special_text, other_tags, graphics=True,
 iter__=None):
     if gajim.interface.pointim_sharp_slash_re.match(special_text):
         # insert post num #123456//
         buffer_, iter_, tag = self.get_iter_and_tag('pointim_sharp_slash')
         buffer_.insert_with_tags(iter__, special_text, tag)
         self.last_pointim_num = special_text
         self.textview.plugin_modified = True
         return
     if gajim.interface.pointim_nick_re.match(special_text):
         # insert pointim nick @nickname////
         buffer_, iter_, tag = self.get_iter_and_tag('pointim_nick')
         mark = buffer_.create_mark(None, iter__, True)
         nick = special_text[1:].rstrip(':')
         buffer_.insert_with_tags(iter__, special_text, tag)
         # insert avatars
         if not self.plugin.config['SHOW_AVATARS']:
             self.textview.plugin_modified = True
             return
         b_nick = buffer_.get_text(buffer_.get_start_iter(),
             buffer_.get_iter_at_mark(mark),False)
         if self.plugin.config['ONLY_AUTHOR_AVATAR'] and not \
         special_text.endswith(':') and b_nick[-9:] not in ('Subscribed to '
         ):
             self.textview.plugin_modified = True
             return
         if self.plugin.config['ONLY_FIRST_AVATAR']:
             if b_nick[-9:] not in ('Reply by ', 'message from ', 'ended by ',
             'Subscribed to '):
                 if b_nick[-2] != gajim.config.get('after_nickname'):
                     self.textview.plugin_modified = True
                     return
                 elif b_nick[-1] == '\n':
                     self.textview.plugin_modified = True
                     return
         conn = gajim.connections[self.chat_control.account]
         if not conn.connected:
             self.textview.plugin_modified = True
             return
         # search id in the db
         query = "select nick, id from person where nick = :nick"
         self.plugin.cursor.execute(query, {'nick':nick})
         db_item = self.plugin.cursor.fetchone()
         if db_item:
             # nick in the db
             pixbuf = self.get_avatar(db_item[1], nick, True)
             if not pixbuf:
                 self.textview.plugin_modified = True
                 return
             end_iter = buffer_.get_iter_at_mark(mark)
             anchor = buffer_.create_child_anchor(end_iter)
             img = TextViewImage(anchor, nick)
             img.set_from_pixbuf(pixbuf)
             img.show()
             self.textview.tv.add_child_at_anchor(img, anchor)
             self.textview.plugin_modified = True
             return
         else:
             # nick not in the db
             gobject.idle_add(self.get_new_avatar, mark, nick)
             return
     if gajim.interface.pointim_pic_re.match(special_text) and \
         self.plugin.config['SHOW_PREVIEW']:
         # show pics preview
         buffer_, iter_, tag = self.get_iter_and_tag('url')
         mark = buffer_.create_mark(None, iter_, True)
         buffer_.insert_with_tags(iter_, special_text, tag)
         uid = special_text.split('/')[-1]
         url = "http://i.pointim.com/photos-512/%s" % uid
         gajim.thread_interface(self.insert_pic_preview, [mark, special_text,
             url])
         self.textview.plugin_modified = True
         return
Example #6
0
        def upload_file(stanza):
            slot = stanza.getTag("slot")
            if not slot:
                progress_window.close_dialog()
                log.error("got unexpected stanza: "+str(stanza))
                error = stanza.getTag("error")
                if error and error.getTag("text"):
                    ErrorDialog(_('Could not request upload slot'), 
                                _('Got unexpected response from server: %s') % str(error.getTagData("text")),
                                transient_for=self.chat_control.parent_win.window)
                else:
                    ErrorDialog(_('Could not request upload slot'), 
                                _('Got unexpected response from server (protocol mismatch??)'),
                                transient_for=self.chat_control.parent_win.window)
                return

            try:
                if self.encrypted_upload:
                    key = os.urandom(32)
                    iv = os.urandom(16)
                    data = StreamFileWithProgress(path_to_file,
                                                  "rb",
                                                  progress_window.update_progress,
                                                  self.encrypted_upload, key, iv)
                else:
                    data = StreamFileWithProgress(path_to_file,
                                                  "rb",
                                                  progress_window.update_progress)
            except:
                progress_window.close_dialog()
                ErrorDialog(_('Could not open file'), 
                            _('Exception raised while opening file (see error log for more information)'),
                            transient_for=self.chat_control.parent_win.window)
                raise       # fill error log with useful information

            put = slot.getTag("put")
            get = slot.getTag("get")
            if not put or not get:
                progress_window.close_dialog()
                log.error("got unexpected stanza: " + str(stanza))
                ErrorDialog(_('Could not request upload slot'), 
                            _('Got unexpected response from server (protocol mismatch??)'),
                            transient_for=self.chat_control.parent_win.window)
                return

            def upload_complete(response_code):
                if response_code == 0:
                    return      # Upload was aborted
                if response_code >= 200 and response_code < 300:
                    log.info("Upload completed successfully")
                    xhtml = None
                    is_image = mime_type.split('/', 1)[0] == 'image'
                    if (not isinstance(self.chat_control, chat_control.ChatControl) or not self.chat_control.gpg_is_active) and \
                        self.dialog_type == 'image' and is_image and not self.encrypted_upload:

                        progress_messages.put(_('Calculating (possible) image thumbnail...'))
                        thumb = None
                        quality_steps = (100, 80, 60, 50, 40, 35, 30, 25, 23, 20, 18, 15, 13, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
                        with open(path_to_file, 'rb') as content_file:
                            thumb = urllib2.quote(base64.standard_b64encode(content_file.read()), '')
                        if thumb and len(thumb) < max_thumbnail_size:
                            quality = 100
                            log.info("Image small enough (%d bytes), not resampling" % len(thumb))
                        elif pil_available:
                            log.info("PIL available, using it for image downsampling")
                            try:
                                for quality in quality_steps:
                                    thumb = Image.open(path_to_file)
                                    thumb.thumbnail((max_thumbnail_dimension, max_thumbnail_dimension), Image.ANTIALIAS)
                                    output = BytesIO()
                                    thumb.save(output, format='JPEG', quality=quality, optimize=True)
                                    thumb = output.getvalue()
                                    output.close()
                                    thumb = urllib2.quote(base64.standard_b64encode(thumb), '')
                                    log.debug("pil thumbnail jpeg quality %d produces an image of size %d..." % (quality, len(thumb)))
                                    if len(thumb) < max_thumbnail_size:
                                        break
                            except:
                                thumb = None
                        else:
                            thumb = None
                        if not thumb:
                            log.info("PIL not available, using GTK for image downsampling")
                            temp_file = None
                            try:
                                with open(path_to_file, 'rb') as content_file:
                                    thumb = content_file.read()
                                loader = gtk.gdk.PixbufLoader()
                                loader.write(thumb)
                                loader.close()
                                pixbuf = loader.get_pixbuf()
                                scaled_pb = self.get_pixbuf_of_size(pixbuf, max_thumbnail_dimension)
                                handle, temp_file = tempfile.mkstemp(suffix='.jpeg', prefix='gajim_httpupload_scaled_tmp', dir=gajim.TMP)
                                log.debug("Saving temporary jpeg image to '%s'..." % temp_file)
                                os.close(handle)
                                for quality in quality_steps:
                                    scaled_pb.save(temp_file, "jpeg", {"quality": str(quality)})
                                    with open(temp_file, 'rb') as content_file:
                                        thumb = content_file.read()
                                    thumb = urllib2.quote(base64.standard_b64encode(thumb), '')
                                    log.debug("gtk thumbnail jpeg quality %d produces an image of size %d..." % (quality, len(thumb)))
                                    if len(thumb) < max_thumbnail_size:
                                        break
                            except:
                                thumb = None
                            finally:
                                if temp_file:
                                    os.unlink(temp_file)
                        if thumb:
                            if len(thumb) > max_thumbnail_size:
                                log.info("Couldn't compress image enough, not sending any thumbnail")
                            else:
                                log.info("Using thumbnail jpeg quality %d (image size: %d bytes)" % (quality, len(thumb)))
                                xhtml = '<body><br/><a href="%s"> <img alt="%s" src="data:image/png;base64,%s"/> </a></body>' % \
                                    (get.getData(), get.getData(), thumb)
                    progress_window.close_dialog()
                    id_ = gajim.get_an_id()
                    def add_oob_tag():
                        pass
                    if self.encrypted_upload:
                        keyAndIv = '#' + binascii.hexlify(iv) + binascii.hexlify(key)
                        self.chat_control.send_message(message=get.getData() + keyAndIv, xhtml=None)
                    else:
                        self.chat_control.send_message(message=get.getData(), xhtml=xhtml)
                    self.chat_control.msg_textview.grab_focus()
                else:
                    progress_window.close_dialog()
                    log.error("got unexpected http upload response code: " + str(response_code))
                    ErrorDialog(_('Could not upload file'),
                                _('Got unexpected http response code from server: ') + str(response_code),
                                transient_for=self.chat_control.parent_win.window)
            
            def uploader():
                progress_messages.put(_('Uploading file via HTTP...'))
                try:
                    headers = {'User-Agent': 'Gajim %s' % gajim.version,
                               'Content-Type': mime_type}
                    request = urllib2.Request(put.getData().encode("utf-8"), data=data, headers=headers)
                    request.get_method = lambda: 'PUT'
                    log.debug("opening urllib2 upload request...")
                    transfer = urllib2.urlopen(request, timeout=30)
                    log.debug("urllib2 upload request done, response code: " + str(transfer.getcode()))
                    return transfer.getcode()
                except UploadAbortedException:
                    log.info("Upload aborted")
                except:
                    progress_window.close_dialog()
                    ErrorDialog(_('Could not upload file'),
                                _('Got unexpected exception while uploading file (see error log for more information)'),
                                transient_for=self.chat_control.parent_win.window)
                    raise       # fill error log with useful information
                return 0

            log.info("Uploading file to '%s'..." % str(put.getData()))
            log.info("Please download from '%s' later..." % str(get.getData()))

            gajim.thread_interface(uploader, [], upload_complete)
Example #7
0
class Base(object):
    def __init__(self, plugin, chat_control):
        self.plugin = plugin
        self.chat_control = chat_control
        self.textview = self.chat_control.conv_textview
        if os.name == 'nt':
            self.backend = backend
        else:
            self.backend = default_backend()

    def print_special_text(self,
                           special_text,
                           other_tags,
                           graphics=True,
                           iter_=None):
        # remove qip bbcode
        special_text = special_text.rsplit('[/img]')[0]

        if special_text.startswith('www.'):
            special_text = 'http://' + special_text
        if special_text.startswith('ftp.'):
            special_text = 'ftp://' + special_text

        parts = urlparse(special_text)
        if parts.scheme not in ["https", "http", "ftp", "ftps"] or \
                not parts.netloc:
            log.info("Not accepting URL for image preview: %s" % special_text)
            return

        buffer_ = self.textview.tv.get_buffer()
        if not iter_:
            iter_ = buffer_.get_end_iter()

        # Detect XHTML-IM link
        ttt = buffer_.get_tag_table()
        tags_ = [(ttt.lookup(t) if isinstance(t, str) else t)
                 for t in other_tags]
        for t in tags_:
            is_xhtml_link = getattr(t, 'href', None)
            if is_xhtml_link:
                break

        # Show URL, until image is loaded (if ever)
        repl_start = buffer_.create_mark(None, iter_, True)
        buffer_.insert_with_tags(iter_, special_text, \
            *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
        repl_end = buffer_.create_mark(None, iter_, True)

        # First get the http head request with does not fetch data, just headers
        gajim.thread_interface(self._get_http_head,
                               [self.textview.account, special_text],
                               self._check_mime_size,
                               [special_text, repl_start, repl_end])

        # Don't print the URL in the message window (in the calling function)
        self.textview.plugin_modified = True

    def _check_mime_size(self, (file_mime, file_size), url, repl_start,
                         repl_end):
        # Check if mime type is acceptable
        if file_mime == '' and file_size == 0:
            log.info(
                "Failed to load HEAD Request for URL: '%s' (see debug log for more info)"
                % url)
            # URL is already displayed
            return
        if file_mime.lower() not in ACCEPTED_MIME_TYPES:
            log.info("Not accepted mime type '%s' for URL: '%s'" %
                     (file_mime.lower(), url))
            # URL is already displayed
            return
        # Check if file size is acceptable
        if file_size > self.plugin.config['MAX_FILE_SIZE'] or file_size == 0:
            log.info("File size (%s) too big or unknown (zero) for URL: '%s'" %
                     (str(file_size), url))
            # URL is already displayed
            return

        # check for encryption (conversations mode)
        urlparts = urlparse(url)
        key = ''
        iv = ''
        if len(urlparts.fragment):
            fragment = []
            for i in range(0, len(urlparts.fragment), 2):
                fragment.append(chr(int(urlparts.fragment[i:i + 2], 16)))
            fragment = ''.join(fragment)
            key = fragment[16:]
            iv = fragment[:16]

        # decrypt if the encryption parameters are correct
        if len(urlparts.fragment) and len(key) == 32 and len(iv) == 16:

            def _decryptor(
                (mem, alt), url, file_mime, repl_start, repl_end, key, iv):
                if not mem:
                    log.error('Could not download image for URL: %s -- %s' %
                              (url, alt))
                    return
                # start self._decrypt_url() in own thread and self._update_img() afterwards
                gajim.thread_interface(
                    self._decrypt_url, [(mem, alt), key, iv, url],
                    self._update_img,
                    [url, file_mime, repl_start, repl_end, True])

            # Start downloading image (_decryptor is callback when download has finished)
            gajim.thread_interface(self._download_image, [
                self.textview.account, {
                    'src': url,
                    'max_size': self.plugin.config['MAX_FILE_SIZE']
                }
            ], _decryptor, [url, file_mime, repl_start, repl_end, key, iv])
Example #8
0
                    self._decrypt_url, [(mem, alt), key, iv, url],
                    self._update_img,
                    [url, file_mime, repl_start, repl_end, True])

            # Start downloading image (_decryptor is callback when download has finished)
            gajim.thread_interface(self._download_image, [
                self.textview.account, {
                    'src': url,
                    'max_size': self.plugin.config['MAX_FILE_SIZE']
                }
            ], _decryptor, [url, file_mime, repl_start, repl_end, key, iv])
        else:
            # Start downloading image (self._update_img() is callback when download has finished)
            gajim.thread_interface(self._download_image, [
                self.textview.account, {
                    'src': url,
                    'max_size': self.plugin.config['MAX_FILE_SIZE']
                }
            ], self._update_img, [url, file_mime, repl_start, repl_end])

    def _decrypt_url(self, (mem, alt), key, iv, url):
        try:
            log.info("Before decrypt image")
            if decryption_available:
                log.info("Fast decrypt")
                mem = self.aes_decrypt_fast(key, iv, mem)
            else:
                log.info("Slow decrypt")
                mem = aes_decrypt(key, iv, mem)
            log.info("After decrypt image")
        except Exception:
            log.error(
Example #9
0
    def print_special_text(self,
                           tv,
                           special_text,
                           other_tags,
                           graphics=True,
                           iter_=None):
        conv_textview = tv
        textview = tv.tv
        # geo:48.2057365,16.3435941
        if not special_text.startswith('geo:'):
            return

        buffer_ = textview.get_buffer()
        if not iter_:
            iter_ = buffer_.get_end_iter()

        textview.plugin_modified = True

        # Show URL, until image is loaded (if ever)
        ttt = buffer_.get_tag_table()
        repl_start = buffer_.create_mark(None, iter_, True)
        buffer_.insert_with_tags(
            iter_, special_text,
            *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
        repl_end = buffer_.create_mark(None, iter_, True)

        zoom = 17
        size = 250
        color = 'blue'

        coordinates = special_text.split(':')[1]

        lat = coordinates.split(',')[0]
        lon = coordinates.split(',')[1]

        filename = coordinates.replace(',', '_').replace('.', '-')
        filepath = os.path.join(self.thumbpath, filename)

        provider = self.config['preview_provider']

        # Google
        if provider == 0:
            url = 'https://maps.googleapis.com/maps/api/staticmap?center={}' \
                  '&zoom={}&size={}x{}&markers=color:{}' \
                  '|label:S|{}'.format(coordinates, zoom, size, size,
                                       color, coordinates)

            weburl = 'https://www.google.at/maps/place/{}'.format(coordinates)
        else:
            # Mapquest / OSM
            apikey = 'F7x36jLVv2hiANVAXmhwvUB044XvGASh'

            url = 'https://open.mapquestapi.com/staticmap/v4/' \
                  'getmap?key={}&center={}&zoom={}&size={},{}&type=map' \
                  '&imagetype=png&pois={},{}&scalebar=false' \
                  .format(apikey, coordinates, zoom, size, size, color,
                          coordinates)

            weburl = 'http://www.openstreetmap.org/' \
                     '?mlat={}&mlon={}#map={}/{}/{}&layers=N' \
                     .format(lat, lon, zoom, lat, lon)

        log.debug(url)

        if os.path.exists(filepath):
            gajim.thread_interface(self.load_thumbnail, [filepath],
                                   self.updatechat,
                                   [weburl, repl_start, repl_end, textview])
        else:
            gajim.thread_interface(self.download, [url, filepath],
                                   self.updatechat,
                                   [weburl, repl_start, repl_end, textview])

        # Don't print the URL in the message window (in the calling function)
        conv_textview.plugin_modified = True
Example #10
0
    def print_special_text(self,
                           special_text,
                           other_tags,
                           graphics=True,
                           iter_=None):
        # remove qip bbcode
        special_text = special_text.rsplit('[/img]')[0]

        if special_text.startswith('www.'):
            special_text = 'http://' + special_text
        if special_text.startswith('ftp.'):
            special_text = 'ftp://' + special_text

        urlparts = urlparse(special_text)
        if urlparts.scheme not in ["https", "http", "ftp", "ftps"] or \
                not urlparts.netloc:
            log.info("Not accepting URL for image preview: %s" % special_text)
            return

        # Don't print the URL in the message window (in the calling function)
        self.textview.plugin_modified = True

        buffer_ = self.textview.tv.get_buffer()
        if not iter_:
            iter_ = buffer_.get_end_iter()

        # Show URL, until image is loaded (if ever)
        ttt = buffer_.get_tag_table()
        repl_start = buffer_.create_mark(None, iter_, True)
        buffer_.insert_with_tags(
            iter_, special_text,
            *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
        repl_end = buffer_.create_mark(None, iter_, True)

        filename = os.path.basename(urlparts.path)
        ext = os.path.splitext(filename)[1]
        name = os.path.splitext(filename)[0]
        namehash = hashlib.sha1(special_text).hexdigest()
        newfilename = name + '_' + namehash + ext
        thumbfilename = name + '_' + namehash + '_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]

        key = ''
        iv = ''
        encrypted = False
        if len(urlparts.fragment):
            fragment = []
            try:
                for i in range(0, len(urlparts.fragment), 2):
                    fragment.append(chr(int(urlparts.fragment[i:i + 2], 16)))
                fragment = ''.join(fragment)
                key = fragment[16:]
                iv = fragment[:16]
                if len(key) == 32 and len(iv) == 16:
                    encrypted = True
            except:
                pass

        # file exists but thumbnail got deleted
        if os.path.exists(filepath) and not os.path.exists(thumbpath):
            with open(filepath, 'rb') as f:
                mem = f.read()
                f.closed
            gajim.thread_interface(
                self._save_thumbnail, [thumbpath, (mem, '')], self._update_img,
                [special_text, repl_start, repl_end, filepath, encrypted])

        # display thumbnail if already downloadeded
        # (but only if file also exists)
        elif os.path.exists(filepath) and os.path.exists(thumbpath):
            gajim.thread_interface(
                self._load_thumbnail, [thumbpath], self._update_img,
                [special_text, repl_start, repl_end, filepath, encrypted])

        # or download file, calculate thumbnail and finally display it
        else:
            if encrypted and not decryption_available:
                log.debug('Please install Crytography to decrypt pictures')
            else:
                # First get the http head request
                # which does not fetch data, just headers
                # then check the mime type and filesize
                gajim.thread_interface(get_http_head,
                                       [self.textview.account, special_text],
                                       self._check_mime_size, [
                                           special_text, repl_start, repl_end,
                                           filepaths, key, iv, encrypted
                                       ])
Example #11
0
        if file_size > self.plugin.config['MAX_FILE_SIZE'] or file_size == 0:
            log.info("File size (%s) too big or unknown (zero) for URL: '%s'" %
                     (str(file_size), url))
            # URL is already displayed
            return

        attributes = {
            'src': url,
            'max_size': self.plugin.config['MAX_FILE_SIZE'],
            'filepaths': filepaths,
            'key': key,
            'iv': iv
        }

        gajim.thread_interface(
            self._download_image,
            [self.textview.account, attributes, encrypted], self._update_img,
            [url, repl_start, repl_end, filepaths[0], encrypted])

    def _download_image(self, account, attributes, encrypted):
        filepath = attributes['filepaths'][0]
        thumbpath = attributes['filepaths'][1]
        key = attributes['key']
        iv = attributes['iv']
        mem, alt = get_http_file(account, attributes)

        # Decrypt file if necessary
        if encrypted:
            mem = self._aes_decrypt_fast(key, iv, mem)

        try:
            # Write file to harddisk
Example #12
0
    def _process_img(self, attrs, loaded=None):
        '''Process a img tag.
        '''
        mem = ''
        update = False
        pixbuf = None
        replace_mark = None
        replace_tags = None

        try:
            if attrs['src'].startswith('data:image/'):
                # The "data" URL scheme http://tools.ietf.org/html/rfc2397
                import base64
                img = attrs['src'].split(',')[1]
                mem = base64.standard_b64decode(urllib2.unquote(img))
            elif loaded is not None:
                (mem, alt, replace_mark, replace_tags) = loaded
                update = True
            else:
                if self.conv_textview:
                    img_mark = self.textbuf.create_mark(None, self.iter, True)
                    gajim.thread_interface(helpers.download_image, [
                        self.conv_textview.account, attrs], self._update_img,
                        [attrs, img_mark, self._get_style_tags()])
                    alt = attrs.get('alt', '')
                    if alt:
                        alt += '\n'
                    alt += _('Loading')
                    pixbuf = get_icon_pixmap('gtk-no')
            if mem:
                # Caveat: GdkPixbuf is known not to be safe to load
                # images from network... this program is now potentially
                # hackable ;)
                loader = gtk.gdk.PixbufLoader()
                dims = [0, 0]
                def height_cb(length):
                    dims[1] = length
                def width_cb(length):
                    dims[0] = length
                # process width and height attributes
                w = attrs.get('width')
                h = attrs.get('height')
                # override with width and height styles
                for attr, val in style_iter(attrs.get('style', '')):
                    if attr == 'width':
                        w = val
                    elif attr == 'height':
                        h = val
                if w:
                    self._parse_length(w, False, False, 1, 1000, width_cb)
                if h:
                    self._parse_length(h, False, False, 1, 1000, height_cb)
                def set_size(pixbuf, w, h, dims):
                    """
                    FIXME: Floats should be relative to the whole textview, and
                    resize with it. This needs new pifbufs for every resize,
                    gtk.gdk.Pixbuf.scale_simple or similar.
                    """
                    if isinstance(dims[0], float):
                        dims[0] = int(dims[0]*w)
                    elif not dims[0]:
                        dims[0] = w
                    if isinstance(dims[1], float):
                        dims[1] = int(dims[1]*h)
                    if not dims[1]:
                        dims[1] = h
                    loader.set_size(*dims)
                if w or h:
                    loader.connect('size-prepared', set_size, dims)
                loader.write(mem)
                loader.close()
                pixbuf = loader.get_pixbuf()
                alt = attrs.get('alt', '')
            working_iter = self.iter
            if replace_mark is not None:
                working_iter = self.textbuf.get_iter_at_mark(replace_mark)
                next_iter = working_iter.copy()
                next_iter.forward_char()
                self.textbuf.delete(working_iter, next_iter)
                self.textbuf.delete_mark(replace_mark)
            if pixbuf is not None:
                if replace_mark:
                    tags = replace_tags
                else:
                    tags = self._get_style_tags()
                if tags:
                    tmpmark = self.textbuf.create_mark(None, working_iter, True)
                self.textbuf.insert_pixbuf(working_iter, pixbuf)
                self.starting = False
                if tags:
                    start = self.textbuf.get_iter_at_mark(tmpmark)
                    for tag in tags:
                        self.textbuf.apply_tag(tag, start, working_iter)
                    self.textbuf.delete_mark(tmpmark)
            else:
                self._insert_text('[IMG: %s]' % alt, working_iter)
        except Exception, ex:
            log.error('Error loading image ' + str(ex))
            pixbuf = None
            alt = attrs.get('alt', 'Broken image')
            try:
                loader.close()
            except Exception:
                pass
Example #13
0
 def print_special_text(self, special_text, other_tags, graphics=True,
 iter__=None):
     if gajim.interface.sharp_slash_re.match(special_text):
         # insert post num #123456//
         buffer_, iter_, tag = self.get_iter_and_tag('sharp_slash')
         buffer_.insert_with_tags(iter__, special_text, tag)
         self.last_juick_num = special_text
         self.textview.plugin_modified = True
         return
     if gajim.interface.juick_nick_re.match(special_text):
         # insert juick nick @nickname////
         buffer_, iter_, tag = self.get_iter_and_tag('juick_nick')
         mark = buffer_.create_mark(None, iter__, True)
         nick = special_text[1:].rstrip(':')
         buffer_.insert_with_tags(iter__, special_text, tag)
         # insert avatars
         if not self.plugin.config['SHOW_AVATARS']:
             self.textview.plugin_modified = True
             return
         b_nick = buffer_.get_text(buffer_.get_start_iter(),
             buffer_.get_iter_at_mark(mark),False)
         if self.plugin.config['ONLY_AUTHOR_AVATAR'] and not \
         special_text.endswith(':') and b_nick[-9:] not in ('Subscribed to '
         ):
             self.textview.plugin_modified = True
             return
         if self.plugin.config['ONLY_FIRST_AVATAR']:
             if b_nick[-9:] not in ('Reply by ', 'message from ', 'ended by ',
             'Subscribed to '):
                 if b_nick[-2] != gajim.config.get('after_nickname'):
                     self.textview.plugin_modified = True
                     return
                 elif b_nick[-1] == '\n':
                     self.textview.plugin_modified = True
                     return
         conn = gajim.connections[self.chat_control.account]
         if not conn.connected:
             self.textview.plugin_modified = True
             return
         # search id in the db
         query = "select nick, id from person where nick = :nick"
         self.plugin.cursor.execute(query, {'nick':nick})
         db_item = self.plugin.cursor.fetchone()
         if db_item:
             # nick in the db
             pixbuf = self.get_avatar(db_item[1], nick, True)
             if not pixbuf:
                 self.textview.plugin_modified = True
                 return
             gobject.idle_add(self.set_avatar, mark, nick, pixbuf)
             self.textview.plugin_modified = True
             return
         else:
             # nick not in the db
             gobject.idle_add(self.get_new_avatar, mark, nick)
             self.textview.plugin_modified = True
             return
     if gajim.interface.juick_pic_re.match(special_text) and \
         self.plugin.config['SHOW_PREVIEW']:
         # show pics preview
         buffer_, iter_, tag = self.get_iter_and_tag('url')
         mark = buffer_.create_mark(None, buffer_.get_end_iter(), True)
         uid = special_text.split('/')[-1]
         url = "http://i.juick.com/photos-512/%s" % uid
         gajim.thread_interface(self.insert_pic_preview, [mark, special_text,
             url, tag])
         self.textview.plugin_modified = True
         return
Example #14
0
 def print_special_text(self, special_text, other_tags, graphics=True, iter__=None):
     if gajim.interface.sharp_slash_re.match(special_text):
         # insert post num #123456//
         buffer_, iter_, tag = self.get_iter_and_tag("sharp_slash")
         buffer_.insert_with_tags(iter__, special_text, tag)
         self.last_juick_num = special_text
         self.textview.plugin_modified = True
         return
     if gajim.interface.juick_nick_re.match(special_text):
         # insert juick nick @nickname////
         buffer_, iter_, tag = self.get_iter_and_tag("juick_nick")
         mark = buffer_.create_mark(None, iter__, True)
         nick = special_text[1:].rstrip(":")
         buffer_.insert_with_tags(iter__, special_text, tag)
         # insert avatars
         if not self.plugin.config["SHOW_AVATARS"]:
             self.textview.plugin_modified = True
             return
         b_nick = buffer_.get_text(buffer_.get_start_iter(), buffer_.get_iter_at_mark(mark), False)
         if (
             self.plugin.config["ONLY_AUTHOR_AVATAR"]
             and not special_text.endswith(":")
             and b_nick[-9:] not in ("Subscribed to ")
         ):
             self.textview.plugin_modified = True
             return
         if self.plugin.config["ONLY_FIRST_AVATAR"]:
             if b_nick[-9:] not in ("Reply by ", "message from ", "ended by ", "Subscribed to "):
                 if b_nick[-2] != gajim.config.get("after_nickname"):
                     self.textview.plugin_modified = True
                     return
                 elif b_nick[-1] == "\n":
                     self.textview.plugin_modified = True
                     return
         conn = gajim.connections[self.chat_control.account]
         if not conn.connected:
             self.textview.plugin_modified = True
             return
         # search id in the db
         query = "select nick, id from person where nick = :nick"
         self.plugin.cursor.execute(query, {"nick": nick})
         db_item = self.plugin.cursor.fetchone()
         if db_item:
             # nick in the db
             pixbuf = self.get_avatar(db_item[1], nick, True)
             if not pixbuf:
                 self.textview.plugin_modified = True
                 return
             gobject.idle_add(self.set_avatar, mark, nick, pixbuf)
             self.textview.plugin_modified = True
             return
         else:
             # nick not in the db
             gobject.idle_add(self.get_new_avatar, mark, nick)
             self.textview.plugin_modified = True
             return
     if gajim.interface.juick_pic_re.match(special_text) and self.plugin.config["SHOW_PREVIEW"]:
         # show pics preview
         buffer_, iter_, tag = self.get_iter_and_tag("url")
         mark = buffer_.create_mark(None, buffer_.get_end_iter(), True)
         uid = special_text.split("/")[-1]
         url = "http://i.juick.com/photos-512/%s" % uid
         gajim.thread_interface(self.insert_pic_preview, [mark, special_text, url, tag])
         self.textview.plugin_modified = True
         return
Example #15
0
    def print_special_text(self, special_text, other_tags, graphics=True,
                           iter_=None):
        # remove qip bbcode
        special_text = special_text.rsplit('[/img]')[0]

        if special_text.startswith('www.'):
            special_text = 'http://' + special_text
        if special_text.startswith('ftp.'):
            special_text = 'ftp://' + special_text

        urlparts = urlparse(special_text)
        if urlparts.scheme not in ["https", "http", "ftp", "ftps"] or \
                not urlparts.netloc:
            log.info("Not accepting URL for image preview: %s" % special_text)
            return

        # Don't print the URL in the message window (in the calling function)
        self.textview.plugin_modified = True

        buffer_ = self.textview.tv.get_buffer()
        if not iter_:
            iter_ = buffer_.get_end_iter()

        # Show URL, until image is loaded (if ever)
        ttt = buffer_.get_tag_table()
        repl_start = buffer_.create_mark(None, iter_, True)
        buffer_.insert_with_tags(iter_, special_text,
            *[(ttt.lookup(t) if isinstance(t, str) else t) for t in ["url"]])
        repl_end = buffer_.create_mark(None, iter_, True)

        filename = os.path.basename(urlparts.path)
        ext = os.path.splitext(filename)[1]
        name = os.path.splitext(filename)[0]
        namehash = hashlib.sha1(special_text).hexdigest()
        newfilename = name + '_' + namehash + ext
        thumbfilename = name + '_' + namehash + '_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]

        key = ''
        iv = ''
        encrypted = False
        if len(urlparts.fragment):
            fragment = []
            for i in range(0, len(urlparts.fragment), 2):
                fragment.append(chr(int(urlparts.fragment[i:i + 2], 16)))
            fragment = ''.join(fragment)
            key = fragment[16:]
            iv = fragment[:16]
            if len(key) == 32 and len(iv) == 16:
                encrypted = True

        # file exists but thumbnail got deleted
        if os.path.exists(filepath) and not os.path.exists(thumbpath):
            with open(filepath, 'rb') as f:
                mem = f.read()
                f.closed
            gajim.thread_interface(
                self._save_thumbnail, [thumbpath, (mem, '')],
                self._update_img, [special_text, repl_start,
                                   repl_end, filepath, encrypted])

        # display thumbnail if already downloadeded
        # (but only if file also exists)
        elif os.path.exists(filepath) and os.path.exists(thumbpath):
            gajim.thread_interface(
                self._load_thumbnail, [thumbpath],
                self._update_img, [special_text, repl_start,
                                   repl_end, filepath, encrypted])

        # or download file, calculate thumbnail and finally display it
        else:
            if encrypted and not decryption_available:
                log.debug('Please install Crytography to decrypt pictures')
            else:
                # First get the http head request
                # which does not fetch data, just headers
                # then check the mime type and filesize
                gajim.thread_interface(
                    get_http_head, [self.textview.account, special_text],
                    self._check_mime_size, [special_text, repl_start, repl_end,
                                            filepaths, key, iv, encrypted])
Example #16
0
        # Check if file size is acceptable
        if file_size > self.plugin.config['MAX_FILE_SIZE'] or file_size == 0:
            log.info("File size (%s) too big or unknown (zero) for URL: '%s'"
                     % (str(file_size), url))
            # URL is already displayed
            return

        attributes = {'src': url,
                      'max_size': self.plugin.config['MAX_FILE_SIZE'],
                      'filepaths': filepaths,
                      'key': key,
                      'iv': iv}

        gajim.thread_interface(
            self._download_image, [self.textview.account,
                                   attributes, encrypted],
            self._update_img, [url, repl_start, repl_end,
                               filepaths[0], encrypted])

    def _download_image(self, account, attributes, encrypted):
        filepath = attributes['filepaths'][0]
        thumbpath = attributes['filepaths'][1]
        key = attributes['key']
        iv = attributes['iv']
        mem, alt = get_http_file(account, attributes)

        # Decrypt file if necessary
        if encrypted:
            mem = self._aes_decrypt_fast(key, iv, mem)

        try: