Example #1
0
    def _render_diff(self, req, filename, repos, diff, diff_options):
        """Raw Unified Diff version"""
        req.send_response(200)
        req.send_header('Content-Type', 'text/plain;charset=utf-8')
        req.send_header('Content-Disposition', 'inline;'
                        'filename=%s.diff' % filename)
        req.end_headers()

        mimeview = Mimeview(self.env)
        for old_node, new_node, kind, change in repos.get_changes(**diff):
            # TODO: Property changes

            # Content changes
            if kind == Node.DIRECTORY:
                continue

            new_content = old_content = ''
            new_node_info = old_node_info = ('','')
            mimeview = Mimeview(self.env)

            if old_node:
                old_content = old_node.get_content().read()
                if is_binary(old_content):
                    continue
                old_node_info = (old_node.path, old_node.rev)
                old_content = mimeview.to_unicode(old_content,
                                                  old_node.content_type)
            if new_node:
                new_content = new_node.get_content().read()
                if is_binary(new_content):
                    continue
                new_node_info = (new_node.path, new_node.rev)
                new_path = new_node.path
                new_content = mimeview.to_unicode(new_content,
                                                  new_node.content_type)
            else:
                old_node_path = repos.normalize_path(old_node.path)
                diff_old_path = repos.normalize_path(diff.old_path)
                new_path = posixpath.join(diff.new_path,
                                          old_node_path[len(diff_old_path)+1:])

            if old_content != new_content:
                context = 3
                options = diff_options[1]
                for option in options:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                if not old_node_info[0]:
                    old_node_info = new_node_info # support for 'A'dd changes
                req.write('Index: ' + new_path + CRLF)
                req.write('=' * 67 + CRLF)
                req.write('--- %s (revision %s)' % old_node_info + CRLF)
                req.write('+++ %s (revision %s)' % new_node_info + CRLF)
                for line in unified_diff(old_content.splitlines(),
                                         new_content.splitlines(), context,
                                         ignore_blank_lines='-B' in options,
                                         ignore_case='-i' in options,
                                         ignore_space_changes='-b' in options):
                    req.write(line + CRLF)
Example #2
0
    def process_request(self, req):
        """Process the request. For ClearSilver, return a (template_name,
        content_type) tuple, where `template` is the ClearSilver template to use
        (either a `neo_cs.CS` object, or the file name of the template), and
        `content_type` is the MIME type of the content. For Genshi, return a
        (template_name, data, content_type) tuple, where `data` is a dictionary
        of substitutions for the template.

        For both templating systems, "text/html" is assumed if `content_type` is
        `None`.

        Note that if template processing should not occur, this method can
        simply send the response itself and not return anything.
        """

        # handle image setting
        if req.method == 'POST':
            self.set_default_image(req)
            req.redirect(req.get_header('referer') or req.href(req.path_info))

        # GET default image
        ticket_id, size = self.ticket_id_and_size(req.path_info)
        image = DefaultTicketImage(self.env).default_image(ticket_id, size)
        assert image is not None # TODO better
        images = ImageTrac(self.env).images(ticket_id)
        attachment = Attachment(self.env, 'ticket', ticket_id, images[image][size])
        mimeview = Mimeview(self.env)
        mimetype = mimeview.get_mimetype(attachment.filename)
        req.send(attachment.open().read(), mimetype)
Example #3
0
    def validate_ticket(self, req, ticket):
        """Validate a ticket after it's been populated from user input.
        
        Must return a list of `(field, message)` tuples, one for each problem
        detected. `field` can be `None` to indicate an overall problem with the
        ticket. Therefore, a return value of `[]` means everything is OK."""
        image = req.args.get('ticket_image')

        if hasattr(image, 'fp'):
            mimeview = Mimeview(self.env)
            mimetype = mimeview.get_mimetype(image.filename)
            if mimetype is None:
                return [('ticket_image', 'Uploaded file is not an image')]
            if mimetype.split('/', 1)[0] != 'image':
                return [('ticket_image',
                         'Uploaded file is not an image, instead it is %s' %
                         mimetype)]

            try:
                Image.open(image.file)
            except IOError, e:
                return [('ticket_image', str(e))]

            # store the image temporarily for new tickets
            if ticket.exists:
                self.attach(ticket, image)
            else:
                if not hasattr(self, 'image'):
                    self.image = {}
                self.image[ticket['summary']] = req.args['ticket_image']
Example #4
0
    def validate_ticket(self, req, ticket):
        """Validate a ticket after it's been populated from user input.
        
        Must return a list of `(field, message)` tuples, one for each problem
        detected. `field` can be `None` to indicate an overall problem with the
        ticket. Therefore, a return value of `[]` means everything is OK."""
        image = req.args.get('ticket_image')

        if hasattr(image, 'fp'):
            mimeview = Mimeview(self.env)
            mimetype = mimeview.get_mimetype(image.filename)
            if mimetype is None:
                return[('ticket_image', 'Uploaded file is not an image')]
            if mimetype.split('/',1)[0] != 'image':
                return [('ticket_image', 'Uploaded file is not an image, instead it is %s' % mimetype)]
            
            try:
                Image.open(image.file)
            except IOError, e:
                return[('ticket_image', str(e))]

            # store the image temporarily for new tickets
            if ticket.exists:
                self.attach(ticket, image)
            else:
                if not hasattr(self, 'image'):
                    self.image = {}
                self.image[ticket['summary']] = req.args['ticket_image']
Example #5
0
    def filter_stream(self, req, method, filename, stream, data):
        action = req.args.get('action', '')

        if filename == 'browser.html' and action == 'edit':
            req.perm.require('REPOSITORY_MODIFY')
            # NB TracBrowserOps already inserts javascript and css we need
            # So only add css/javascript needed solely by the editor

            if data['file'] and data['file']['preview']['rendered']:
                max_edit_size = self.max_edit_size
                data['max_edit_size'] = max_edit_size

                # Discard rendered table, replace with textarea of file contents
                # This means reading the file from the repository again
                # N.B. If a file is rendered as something other than a table
                # e.g. due to PreCodeBrowserPlugin this code won't trigger

                # Retrieve the same node that BrowserModule.process_request()
                # used to render the preview.
                # At this point reponame has been removed from data['path']
                # and repos has already been determined
                repos = data['repos']
                path = data['path']
                rev = data['rev']
                node = repos.get_node(path, rev)

                # If node is too large then don't allow editing, abort
                if max_edit_size > 0 and node.content_length > max_edit_size:
                    return stream

                # Open the node and read it
                node_file = node.get_content()
                node_data = node_file.read()

                # Discover the mime type and character encoding of the node
                # Try in order
                #  - svn:mime-type property
                #  - detect from file name and content (BOM)
                #  - use configured default for Trac
                mime_view = Mimeview(self.env)
                mime_type = node.content_type \
                            or mime_view.get_mimetype(node.name, node_data) \
                            or 'text/plain'
                encoding = mime_view.get_charset(node_data, mime_type)

                # Populate template data
                content = mime_view.to_unicode(node_data, mime_type, encoding)
                data['file_content'] = content
                data['file_encoding'] = encoding

                # Replace the already rendered preview with a form and textarea
                bsops_stream = Chrome(self.env).render_template(
                    req, 'file_edit.html', data, fragment=True)
                transf = Transformer('//div[@id="preview"]'
                                     '/table[@class="code"]')
                stream |= transf.replace(
                    bsops_stream.select('//div[@id="bsop_edit"]'))
        return stream
Example #6
0
    def filter_stream(self, req, method, filename, stream, data):
        action = req.args.get('action', '')
        
        if filename == 'browser.html' and action == 'edit':
            req.perm.require('REPOSITORY_MODIFY')
            # NB TracBrowserOps already inserts javascript and css we need
            # So only add css/javascript needed solely by the editor
            
            if data['file'] and data['file']['preview']['rendered']:
                max_edit_size = self.max_edit_size
                data['max_edit_size'] = max_edit_size
                
                # Discard rendered table, replace with textarea of file contents
                # This means reading the file from the repository again
                # N.B. If a file is rendered as something other than a table
                # e.g. due to PreCodeBrowserPlugin this code won't trigger
                
                # Retrieve the same node that BrowserModule.process_request() 
                # used to render the preview.
                # At this point reponame has been removed from data['path']
                # and repos has already been determined
                repos = data['repos']
                path = data['path']
                rev = data['rev']
                node = repos.get_node(path, rev)
                
                # If node is too large then don't allow editing, abort
                if max_edit_size > 0 and node.content_length > max_edit_size:
                    return stream
                
                # Open the node and read it
                node_file = node.get_content() 
                node_data = node_file.read()

                # Discover the mime type and character encoding of the node
                # Try in order
                #  - svn:mime-type property
                #  - detect from file name and content (BOM)
                #  - use configured default for Trac
                mime_view = Mimeview(self.env)
                mime_type = node.content_type \
                            or mime_view.get_mimetype(node.name, node_data) \
                            or 'text/plain'
                encoding = mime_view.get_charset(node_data, mime_type)
                
                # Populate template data
                content = mime_view.to_unicode(node_data, mime_type, encoding)
                data['file_content'] = content               
                data['file_encoding'] = encoding
                
                # Replace the already rendered preview with a form and textarea
                bsops_stream = Chrome(self.env).render_template(req,
                        'file_edit.html', data, fragment=True)
                transf = Transformer('//div[@id="preview"]'
                                     '/table[@class="code"]')
                stream |=  transf.replace(
                        bsops_stream.select('//div[@id="bsop_edit"]'))
        return stream
Example #7
0
def add_backlog_conversion_links(env, req, backlog, backlog_url):
    # TODO: Move tests to new backlog
    mime = Mimeview(env)
    for conversion in mime.get_supported_conversions(BACKLOG_CONVERSION_KEY):
        format = conversion[0]
        title = conversion[1]
        mimetype = conversion[4]
        backlog_href = req.href(backlog_url, backlog.name, backlog.scope, format=format)
        add_link(req, 'alternate', backlog_href, title, mimetype, format)
Example #8
0
    def image(self, ticket):
        """
        return the first image attachment
        or None if there aren't any
        """

        attachments = list(Attachment.select(self.env, 'ticket', ticket.id))
        mimeview = Mimeview(self.env)
        for attachment in attachments:
            mimetype = mimeview.get_mimetype(attachment.filename)
            if not mimetype or mimetype.split('/',1)[0] != 'image':
                continue
            return attachment.filename
def source( req, argument_text, env, aswiki =False):
    from trac.versioncontrol.web_ui.util import get_existing_node, get_path_rev_line
        ## XXX above .util is shaded by trac.util?

    path,rev,line = get_path_rev_line( argument_text)
    from trac.mimeview import Mimeview, get_mimetype, content_to_unicode

    repos = env.get_repository() # req.authname)
    node = get_existing_node( env, repos, path, rev)
    content = node.get_content().read()
    if aswiki:
        mimetype = 'text/x-trac-wiki'
        r = wiki_to_html( content_to_unicode( env, content, mimetype), env=env, req=req)
    else:
        mimetype = get_mimetype( os.path.basename( path) ) or 'text/plain '
        mimeview = Mimeview( env)
        #charset = mimeview.get_charset( content, mimetype) #node.content_type?
        #content = util.to_utf8( content, charset )
        r = mimeview.render( req, mimetype, content)
    return r, None
Example #10
0
    def image_category(self, attachment):
        reverse_sizes = dict([(value, key) for key, value in self.sizes().items()])
        mimeview = Mimeview(self.env)
        mimetype = mimeview.get_mimetype(attachment.filename)
        if mimetype and mimetype.split('/',1)[0] != 'image':
            return None
        filename = attachment.filename
        try:
            size = Image.open(attachment.path).size
        except IOError:
            return None
        for _size in reverse_sizes:
            parts = filename.rsplit('.', 2)
            if len(parts) == 3:
                dimension = '%sx%s' % (_size[0] or '', _size[1] or '')
                if parts[-2] == dimension:
                    filename = '%s.%s' % (parts[0], parts[-1])
                    return (filename, reverse_sizes[_size])

        return (filename, 'original')
Example #11
0
    def image_category(self, attachment):
        reverse_sizes = dict([(value, key)
                              for key, value in self.sizes().items()])
        mimeview = Mimeview(self.env)
        mimetype = mimeview.get_mimetype(attachment.filename)
        if mimetype and mimetype.split('/', 1)[0] != 'image':
            return None
        filename = attachment.filename
        try:
            size = Image.open(attachment.path).size
        except IOError:
            return None
        for _size in reverse_sizes:
            parts = filename.rsplit('.', 2)
            if len(parts) == 3:
                dimension = '%sx%s' % (_size[0] or '', _size[1] or '')
                if parts[-2] == dimension:
                    filename = '%s.%s' % (parts[0], parts[-1])
                    return (filename, reverse_sizes[_size])

        return (filename, 'original')
Example #12
0
    def _render_diff(self, req, filename, repos, diff, diff_options):
        """Raw Unified Diff version"""
        req.send_response(200)
        req.send_header('Content-Type', 'text/plain;charset=utf-8')
        req.send_header('Content-Disposition', 'inline;'
                        'filename=%s.diff' % filename)
        req.end_headers()

        mimeview = Mimeview(self.env)
        for old_node, new_node, kind, change in repos.get_changes(**diff):
            # TODO: Property changes

            # Content changes
            if kind == Node.DIRECTORY:
                continue

            new_content = old_content = ''
            new_node_info = old_node_info = ('','')
            mimeview = Mimeview(self.env)

            if old_node:
                old_content = old_node.get_content().read()
                if is_binary(old_content):
                    continue
                old_node_info = (old_node.path, old_node.rev)
                old_content = mimeview.to_unicode(old_content,
                                                  old_node.content_type)
            if new_node:
                new_content = new_node.get_content().read()
                if is_binary(new_content):
                    continue
                new_node_info = (new_node.path, new_node.rev)
                new_path = new_node.path
                new_content = mimeview.to_unicode(new_content,
                                                  new_node.content_type)
            else:
                old_node_path = repos.normalize_path(old_node.path)
                diff_old_path = repos.normalize_path(diff.old_path)
                new_path = posixpath.join(diff.new_path,
                                          old_node_path[len(diff_old_path)+1:])

            if old_content != new_content:
                context = 3
                options = diff_options[1]
                for option in options:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                if not old_node_info[0]:
                    old_node_info = new_node_info # support for 'A'dd changes
                req.write('Index: ' + new_path + CRLF)
                req.write('=' * 67 + CRLF)
                req.write('--- %s (revision %s)' % old_node_info + CRLF)
                req.write('+++ %s (revision %s)' % new_node_info + CRLF)
                for line in unified_diff(old_content.splitlines(),
                                         new_content.splitlines(), context,
                                         ignore_blank_lines='-B' in options,
                                         ignore_case='-i' in options,
                                         ignore_space_changes='-b' in options):
                    req.write(line + CRLF)
Example #13
0
        def _content_changes(old_node, new_node):
            """Returns the list of differences.

            The list is empty when no differences between comparable files
            are detected, but the return value is None for non-comparable files.
            """
            old_content = old_node.get_content().read()
            if is_binary(old_content):
                return None

            new_content = new_node.get_content().read()
            if is_binary(new_content):
                return None

            mview = Mimeview(self.env)
            old_content = mview.to_unicode(old_content, old_node.content_type)
            new_content = mview.to_unicode(new_content, new_node.content_type)

            if old_content != new_content:
                context = 3
                options = diff_options[1]
                for option in options:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                if context < 0:
                    context = None
                tabwidth = self.config['diff'].getint('tab_width') or \
                           self.config['mimeviewer'].getint('tab_width', 8)
                return hdf_diff(old_content.splitlines(),
                                new_content.splitlines(),
                                context, tabwidth,
                                ignore_blank_lines='-B' in options,
                                ignore_case='-i' in options,
                                ignore_space_changes='-b' in options)
            else:
                return []
Example #14
0
        def _content_changes(old_node, new_node):
            """Returns the list of differences.

            The list is empty when no differences between comparable files
            are detected, but the return value is None for non-comparable files.
            """
            old_content = old_node.get_content().read()
            if is_binary(old_content):
                return None

            new_content = new_node.get_content().read()
            if is_binary(new_content):
                return None

            mview = Mimeview(self.env)
            old_content = mview.to_unicode(old_content, old_node.content_type)
            new_content = mview.to_unicode(new_content, new_node.content_type)

            if old_content != new_content:
                context = 3
                options = diff_options[1]
                for option in options:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                if context < 0:
                    context = None
                tabwidth = self.config['diff'].getint('tab_width') or \
                           self.config['mimeviewer'].getint('tab_width', 8)
                return hdf_diff(old_content.splitlines(),
                                new_content.splitlines(),
                                context, tabwidth,
                                ignore_blank_lines='-B' in options,
                                ignore_case='-i' in options,
                                ignore_space_changes='-b' in options)
            else:
                return []
Example #15
0
        def _content_changes(old_node, new_node):
            """Returns the list of differences.

            The list is empty when no differences between comparable files
            are detected, but the return value is None for non-comparable files.
            """
            mview = Mimeview(self.env)
            if mview.is_binary(old_node.content_type, old_node.path):
                return None
            if mview.is_binary(new_node.content_type, new_node.path):
                return None
            old_content = old_node.get_content().read()
            if mview.is_binary(content=old_content):
                return None
            new_content = new_node.get_content().read()
            if mview.is_binary(content=new_content):
                return None

            old_content = mview.to_unicode(old_content, old_node.content_type)
            new_content = mview.to_unicode(new_content, new_node.content_type)

            if old_content != new_content:
                context = options.get('contextlines', 3)
                if context < 0:
                    context = None
                tabwidth = self.config['diff'].getint('tab_width') or \
                           self.config['mimeviewer'].getint('tab_width', 8)
                ignore_blank_lines = options.get('ignoreblanklines')
                ignore_case = options.get('ignorecase')
                ignore_space = options.get('ignorewhitespace')
                return diff_blocks(old_content.splitlines(),
                                   new_content.splitlines(),
                                   context, tabwidth,
                                   ignore_blank_lines=ignore_blank_lines,
                                   ignore_case=ignore_case,
                                   ignore_space_changes=ignore_space)
            else:
                return []
Example #16
0
    def _render_file(self, req, repos, node, rev=None):
        req.perm.assert_permission('FILE_VIEW')

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = mimeview.get_mimetype(node.name, chunk) or \
                        mime_type or 'text/plain'

        # Eventually send the file directly
        format = req.args.get('format')
        if format in ['raw', 'txt']:
            req.send_response(200)
            req.send_header('Content-Type',
                            format == 'txt' and 'text/plain' or mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified', http_date(node.last_modified))
            if not self.render_unsafe_content:
                # Force browser to download files instead of rendering
                # them, since they might contain malicious code enabling 
                # XSS attacks
                req.send_header('Content-Disposition', 'attachment')
            req.end_headers()

            while 1:
                if not chunk:
                    raise RequestDone
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
        else:
            # The changeset corresponding to the last change on `node` 
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.rev)

            message = changeset.message or '--'
            if self.config['changeset'].getbool('wiki_format_messages'):
                message = wiki_to_html(message, self.env, req,
                                       escape_newlines=True)
            else:
                message = html.PRE(message)
            ZhUnit = {'second':u'秒','seconds':u'秒','minute':u'分钟','minutes':u'分钟','hour':u'小时','hours':u'小时',
                            'day':u'天','days':u'天','year':u'年','years':u'年','month':u'月','months':u'月'}
            tempTime = pretty_timedelta(changeset.date)
            numAndUnit = tempTime.split(' ')
            numAndUnit[1] = ZhUnit.get(numAndUnit[1],numAndUnit[1])
            ZhAge = ' '.join(numAndUnit)            
            req.hdf['file'] = {
                'rev': node.rev,
                'changeset_href': req.href.changeset(node.rev),
                'date': format_datetime(changeset.date),
                'age': ZhAge,
                'size': pretty_size(node.content_length),
                'author': changeset.author or 'anonymous',
                'message': message
            } 

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != 'text/plain':
                plain_href = req.href.browser(node.path, rev=rev, format='txt')
                add_link(req, 'alternate', plain_href, 'Plain Text',
                         'text/plain')

            # add ''Original Format'' alternate link (always)
            raw_href = req.href.browser(node.path, rev=rev, format='raw')
            add_link(req, 'alternate', raw_href, 'Original Format', mime_type)

            self.log.debug("Rendering preview of node %s@%s with mime-type %s"
                           % (node.name, str(rev), mime_type))

            del content # the remainder of that content is not needed

            req.hdf['file'] = mimeview.preview_to_hdf(
                req, node.get_content(), node.get_content_length(), mime_type,
                node.created_path, raw_href, annotations=['lineno'])

            add_stylesheet(req, 'common/css/code.css')
Example #17
0
    def _render_file(self, req, repos, node, rev=None):
        req.perm.assert_permission('FILE_VIEW')

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = mimeview.get_mimetype(node.name, chunk) or \
                        mime_type or 'text/plain'

        # Eventually send the file directly
        format = req.args.get('format')
        if format in ['raw', 'txt']:
            req.send_response(200)
            req.send_header('Content-Type', format == 'txt' and 'text/plain'
                            or mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified', http_date(node.last_modified))
            req.end_headers()

            while 1:
                if not chunk:
                    raise RequestDone
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
        else:
            # The changeset corresponding to the last change on `node`
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.rev)

            message = changeset.message or '--'
            if self.config['changeset'].getbool('wiki_format_messages'):
                message = wiki_to_html(message,
                                       self.env,
                                       req,
                                       escape_newlines=True)
            else:
                message = html.PRE(message)

            req.hdf['file'] = {
                'rev': node.rev,
                'changeset_href': req.href.changeset(node.rev),
                'date': format_datetime(changeset.date),
                'age': pretty_timedelta(changeset.date),
                'size': pretty_size(node.content_length),
                'author': changeset.author or 'anonymous',
                'message': message
            }

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != 'text/plain':
                plain_href = req.href.browser(node.path, rev=rev, format='txt')
                add_link(req, 'alternate', plain_href, 'Plain Text',
                         'text/plain')

            # add ''Original Format'' alternate link (always)
            raw_href = req.href.browser(node.path, rev=rev, format='raw')
            add_link(req, 'alternate', raw_href, u'Format original', mime_type)

            self.log.debug(
                "Rendering preview of node %s@%s with mime-type %s" %
                (node.name, str(rev), mime_type))

            del content  # the remainder of that content is not needed

            req.hdf['file'] = mimeview.preview_to_hdf(
                req,
                node.get_content(),
                node.get_content_length(),
                mime_type,
                node.created_path,
                raw_href,
                annotations=['lineno'])

            add_stylesheet(req, 'common/css/code.css')
Example #18
0
    def _do_actions(self, context, actions):
        for action in actions:
            if action == 'get-file':
                context.req.perm.require('DOWNLOADS_VIEW')

                # Get request arguments.
                download_id = context.req.args.get('id') or 0
                download_file = context.req.args.get('file')

                # Get download.
                if download_id:
                    download = self.get_download(context, download_id)
                else:
                    download = self.get_download_by_file(
                        context, download_file)

                # Check if requested download exists.
                if not download:
                    raise TracError('File not found.')

                # Check resource based permission.
                context.req.perm.require('DOWNLOADS_VIEW',
                                         Resource('downloads', download['id']))

                # Get download file path.
                path = os.path.normpath(
                    os.path.join(self.path, to_unicode(download['id']),
                                 download['file']))
                self.log.debug('path: %s' % (path, ))

                # Increase downloads count.
                new_download = {'count': download['count'] + 1}

                # Edit download.
                self.edit_download(context, download['id'], new_download)

                # Notify change listeners.
                for listener in self.change_listeners:
                    listener.download_changed(context, new_download, download)

                # Commit DB before file send.
                db = self.env.get_db_cnx()
                db.commit()

                # Guess mime type.
                file = open(path.encode('utf-8'), "r")
                file_data = file.read(1000)
                file.close()
                mimeview = Mimeview(self.env)
                mime_type = mimeview.get_mimetype(path, file_data)
                if not mime_type:
                    mime_type = 'application/octet-stream'
                if 'charset=' not in mime_type:
                    charset = mimeview.get_charset(file_data, mime_type)
                    mime_type = mime_type + '; charset=' + charset

                # Return uploaded file to request.
                context.req.send_header(
                    'Content-Disposition', 'attachment;filename="%s"' %
                    (os.path.normpath(download['file'])))
                context.req.send_header('Content-Description',
                                        download['description'])
                context.req.send_file(path.encode('utf-8'), mime_type)

            elif action == 'downloads-list':
                context.req.perm.require('DOWNLOADS_VIEW')

                self.log.debug('visible_fields: %s' % (self.visible_fields, ))

                # Get form values.
                order = context.req.args.get('order') or self.download_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.download_sort_direction == 'desc'

                self.data['order'] = order
                self.data['desc'] = desc
                self.data['has_tags'] = self.env.is_component_enabled(
                    'tractags.api.TagEngine')
                self.data['visible_fields'] = self.visible_fields
                self.data['title'] = self.title
                self.data['description'] = self.get_description(context)
                self.data['downloads'] = self.get_downloads(
                    context, order, desc)
                self.data['visible_fields'] = [
                    visible_field for visible_field in self.visible_fields
                ]

                # Component, versions, etc. are needed only for new download
                # add form.
                if context.req.perm.has_permission('DOWNLOADS_ADD'):
                    self.data['components'] = self.get_components(context)
                    self.data['versions'] = self.get_versions(context)
                    self.data['architectures'] = self.get_architectures(
                        context)
                    self.data['platforms'] = self.get_platforms(context)
                    self.data['types'] = self.get_types(context)

            elif action == 'admin-downloads-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values
                order = context.req.args.get('order') or self.download_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.download_sort_direction == 'desc'
                download_id = int(context.req.args.get('download') or 0)

                self.data['order'] = order
                self.data['desc'] = desc
                self.data['has_tags'] = self.env.is_component_enabled(
                    'tractags.api.TagEngine')
                self.data['download'] = self.get_download(context, download_id)
                self.data['downloads'] = self.get_downloads(
                    context, order, desc)
                self.data['components'] = self.get_components(context)
                self.data['versions'] = self.get_versions(context)
                self.data['architectures'] = self.get_architectures(context)
                self.data['platforms'] = self.get_platforms(context)
                self.data['types'] = self.get_types(context)

            elif action == 'description-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

            elif action == 'description-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                description = context.req.args.get('description')

                # Set new description.
                self.edit_description(context, description)

            elif action == 'downloads-post-add':
                context.req.perm.require('DOWNLOADS_ADD')

                # Get form values.
                file, filename, file_size = self._get_file_from_req(context)
                download = {
                    'file': filename,
                    'description': context.req.args.get('description'),
                    'size': file_size,
                    'time': to_timestamp(datetime.now(utc)),
                    'count': 0,
                    'author': context.req.authname,
                    'tags': context.req.args.get('tags'),
                    'component': context.req.args.get('component'),
                    'version': context.req.args.get('version'),
                    'architecture': context.req.args.get('architecture'),
                    'platform': context.req.args.get('platform'),
                    'type': context.req.args.get('type')
                }

                # Upload file to DB and file storage.
                self._add_download(context, download, file)

                # Close input file.
                file.close()

            elif action == 'downloads-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                download_id = context.req.args.get('id')
                old_download = self.get_download(context, download_id)
                download = {
                    'description': context.req.args.get('description'),
                    'tags': context.req.args.get('tags'),
                    'component': context.req.args.get('component'),
                    'version': context.req.args.get('version'),
                    'architecture': context.req.args.get('architecture'),
                    'platform': context.req.args.get('platform'),
                    'type': context.req.args.get('type')
                }

                # Edit Download.
                self.edit_download(context, download_id, download)

                # Notify change listeners.
                for listener in self.change_listeners:
                    listener.download_changed(context, download, old_download)

            elif action == 'downloads-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected downloads.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]

                # Delete download.
                if selection:
                    for download_id in selection:
                        download = self.get_download(context, download_id)
                        self.log.debug('download: %s' % (download, ))
                        self._delete_download(context, download)

            elif action == 'admin-architectures-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values
                order = context.req.args.get('order') or self.architecture_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.architecture_sort_direction == 'desc'
                architecture_id = int(
                    context.req.args.get('architecture') or 0)

                # Display architectures.
                self.data['order'] = order
                self.data['desc'] = desc
                self.data['architecture'] = self.get_architecture(
                    context, architecture_id)
                self.data['architectures'] = self.get_architectures(
                    context, order, desc)

            elif action == 'architectures-post-add':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                architecture = {
                    'name': context.req.args.get('name'),
                    'description': context.req.args.get('description')
                }

                # Add architecture.
                self.add_architecture(context, architecture)

            elif action == 'architectures-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                architecture_id = context.req.args.get('id')
                architecture = {
                    'name': context.req.args.get('name'),
                    'description': context.req.args.get('description')
                }

                # Add architecture.
                self.edit_architecture(context, architecture_id, architecture)

            elif action == 'architectures-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected architectures.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]

                # Delete architectures.
                if selection:
                    for architecture_id in selection:
                        self.delete_architecture(context, architecture_id)

            elif action == 'admin-platforms-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                order = context.req.args.get('order') or self.platform_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.platform_sort_direction == 'desc'
                platform_id = int(context.req.args.get('platform') or 0)

                # Display platforms.
                self.data['order'] = order
                self.data['desc'] = desc
                self.data['platform'] = self.get_platform(context, platform_id)
                self.data['platforms'] = self.get_platforms(
                    context, order, desc)

            elif action == 'platforms-post-add':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                platform = {
                    'name': context.req.args.get('name'),
                    'description': context.req.args.get('description')
                }

                # Add platform.
                self.add_platform(context, platform)

            elif action == 'platforms-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                platform_id = context.req.args.get('id')
                platform = {
                    'name': context.req.args.get('name'),
                    'description': context.req.args.get('description')
                }

                # Add platform.
                self.edit_platform(context, platform_id, platform)

            elif action == 'platforms-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected platforms.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]

                # Delete platforms.
                if selection:
                    for platform_id in selection:
                        self.delete_platform(context, platform_id)

            elif action == 'admin-types-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values
                order = context.req.args.get('order') or self.type_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.type_sort_direction == 'desc'
                platform_id = int(context.req.args.get('type') or 0)

                # Display platforms.
                self.data['order'] = order
                self.data['desc'] = desc
                self.data['type'] = self.get_type(context, platform_id)
                self.data['types'] = self.get_types(context, order, desc)

            elif action == 'types-post-add':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                type = {
                    'name': context.req.args.get('name'),
                    'description': context.req.args.get('description')
                }

                # Add type.
                self.add_type(context, type)

            elif action == 'types-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                type_id = context.req.args.get('id')
                type = {
                    'name': context.req.args.get('name'),
                    'description': context.req.args.get('description')
                }

                # Add platform.
                self.edit_type(context, type_id, type)

            elif action == 'types-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected types.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]

                # Delete types.
                if selection:
                    for type_id in selection:
                        self.delete_type(context, type_id)
Example #19
0
    def _do_actions(self, context, actions, req_data):
        for action in actions:
            if action == 'get-file':
                context.req.perm.require('DOWNLOADS_VIEW')

                # Get request arguments.
                download_id = context.req.args.get('id') or 0
                download_file = context.req.args.get('file')

                # Get download.
                if download_id:
                    download = self.get_download(context, download_id)
                else:
                    download = self.get_download_by_file(context, download_file)

                # Check if requested download exists.
                if not download:
                    raise TracError('File not found.')

                # Check resource based permission.
                context.req.perm.require('DOWNLOADS_VIEW', Resource('downloads', download['id']))

                filename = os.path.basename(download['file'])
                # Get download file path.
                path = os.path.normpath(os.path.join(self.path, to_unicode(download['id']), filename))
                self.log.debug('path: %s' % (path,))

                # Increase downloads count.
                new_download = {'count' : download['count'] + 1}

                # Edit download.
                self.edit_download(context, download['id'], new_download)

                # Notify change listeners.
                for listener in self.change_listeners:
                    listener.download_changed(context, new_download,
                      download)

                # Commit DB before file send.
                db = self.env.get_db_cnx()
                db.commit()

                # Guess mime type.
                file = open(path.encode('utf-8'), "r")
                file_data = file.read(1000)
                file.close()
                mimeview = Mimeview(self.env)
                mime_type = mimeview.get_mimetype(path, file_data)
                if not mime_type:
                    mime_type = 'application/octet-stream'
                if 'charset=' not in mime_type:
                    charset = mimeview.get_charset(file_data, mime_type)
                    mime_type = mime_type + '; charset=' + charset

                # Return uploaded file to request.
                context.req.send_header('Content-Disposition', 'attachment;filename="%s"' % (os.path.normpath(download['file'])))
                context.req.send_header('Content-Description', download['description'])
                try:
                    context.req.send_file(path.encode('utf-8'), mime_type)
                except RequestDone:
                    try:
                        for listener in self.download_listeners:
                            listener.downloaded(context, download)
                    finally:
                        raise RequestDone

            elif action == 'downloads-list':
                context.req.perm.require('DOWNLOADS_VIEW')

                # Get form values.
                order = context.req.args.get('order') or self.download_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.download_sort_direction

                req_data['order'] = order
                req_data['desc'] = desc
                req_data['has_tags'] = self.env.is_component_enabled('tractags.api.TagEngine')
                req_data['visible_fields'] = self.visible_fields
                req_data['title'] = self.title
                req_data['description'] = self.get_description(context)
                req_data['downloads'] = self.get_downloads(context, order, desc)
                req_data['visible_fields'] = [visible_field for visible_field
                  in self.visible_fields]

                # Component, versions, etc. are needed only for new download
                # add form.
                if context.req.perm.has_permission('DOWNLOADS_ADD'):
                    req_data['components'] = self.get_components(context)
                    req_data['versions'] = self.get_versions(context)
                    req_data['platforms'] = self.get_platforms(context)
                    req_data['types'] = self.get_types(context)

            elif action == 'admin-downloads-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values
                order = context.req.args.get('order') or self.download_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.download_sort_direction
                download_id = safe_int(context.req.args.get('download', '0'))

                req_data['supported_files'] = ', '.join(self.ext)
                req_data['order'] = order
                req_data['desc'] = desc
                req_data['has_tags'] = self.env.is_component_enabled('tractags.api.TagEngine')
                req_data['download'] = self.get_download(context, download_id)
                req_data['downloads'] = self.get_downloads(context, order, desc)
                req_data['components'] = self.get_components(context)
                req_data['versions'] = self.get_versions(context)
                req_data['platforms'] = self.get_platforms(context)
                req_data['types'] = self.get_types(context)

                if not req_data['components']:
                    req_data['cstate'] = {'disabled': 'disabled'}
                if not req_data['versions']:
                    req_data['vstate'] = {'disabled': 'disabled'}
                if not req_data['platforms']:
                    req_data['pstate'] = {'disabled': 'disabled'}
                if not req_data['types']:
                    req_data['tstate'] = {'disabled': 'disabled'}
            elif action == 'description-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

            elif action == 'description-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                description = context.req.args.get('description')

                # Set new description.
                self.edit_description(context, description)

            elif action == 'downloads-post-add':
                context.req.perm.require('DOWNLOADS_ADD')

                # Get form values.
                file, filename, file_size = self._get_file_from_req(context)
                download = {'file' : filename,
                            'description' : context.req.args.get('description'),
                            'size' : file_size,
                            'time' : to_timestamp(datetime.now(utc)),
                            'count' : 0,
                            'author' : context.req.authname,
                            'tags' : context.req.args.get('tags'),
                            'component' : context.req.args.get('component'),
                            'version' : context.req.args.get('version'),
                            'platform' : context.req.args.get('platform'),
                            'type' : context.req.args.get('type')}

                # Upload file to DB and file storage.
                self._add_download(context, download, file)

                # Close input file.
                file.close()

            elif action == 'downloads-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                download_id = safe_int(context.req.args.get('id'))
                old_download = self.get_download(context, download_id)
                download = {'description' : context.req.args.get('description'),
                            'tags' : context.req.args.get('tags'),
                            'component' : context.req.args.get('component'),
                            'version' : context.req.args.get('version'),
                            'platform' : context.req.args.get('platform'),
                            'type' : context.req.args.get('type')}

                try:
                    # NOTE: if only description changed, file cannot be found and this raises TracError
                    file, filename, file_size = self._get_file_from_req(context)

                    if old_download['file'] != filename or old_download['size'] != file_size:
                        download['file'] = filename
                        download['size'] = file_size
                        download['author'] = context.req.authname
                        download['time'] = to_timestamp(datetime.now(utc))
                        self._add_download(context, download, file, {'id': download_id, 'file': old_download['file']})
                    else:
                        # Edit Download.
                        self.edit_download(context, download_id, download)

                except:
                    # Edit Download.
                    self.edit_download(context, download_id, download)

                finally:
                    # Close input file.
                    if 'file' in locals():
                        file.close()

                # Notify change listeners.
                for listener in self.change_listeners:
                    listener.download_changed(context, download, old_download)
            elif action == 'downloads-featured':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected downloads.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]
                if selection:
                    self.clean_featured(context)
                    self.edit_featured(context, selection)
            elif action == 'downloads-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')
                # Get selected downloads.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]
                # Delete download.
                if selection:
                    for download_id in selection:
                        download_id = safe_int(download_id)
                        download = self.get_download(context, download_id)
                        self.log.debug('download: %s' % (download,))
                        self._delete_download(context, download)

            elif action == 'admin-platforms-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                order = context.req.args.get('order') or self.platform_sort
                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.platform_sort_direction
                platform_id = safe_int(context.req.args.get('platform','0'))

                if order not in self.platform_sort_options:
                    raise TracError('Invalid sort order')

                # Display platforms.
                req_data['order'] = order
                req_data['desc'] = desc
                req_data['platform'] = self.get_platform(context,
                  platform_id)
                req_data['platforms'] = self.get_platforms(context, order,
                  desc)

            elif action == 'platforms-post-add':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                platform = {'name' : context.req.args.get('name'),
                            'description' : context.req.args.get('description')}

                # Add platform.
                self.add_platform(context, platform)

            elif action == 'platforms-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                platform_id = context.req.args.get('id')
                platform = {'name' : context.req.args.get('name'),
                            'description' : context.req.args.get('description')}

                # Add platform.
                self.edit_platform(context, platform_id, platform)

            elif action == 'platforms-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected platforms.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]

                # Delete platforms.
                if selection:
                    for platform_id in selection:
                        platform_id = safe_int(platform_id)
                        self.delete_platform(context, platform_id)

            elif action == 'admin-types-list':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values
                order = context.req.args.get('order') or self.type_sort
                if order not in self.type_sort_options:
                    self.log.debug('Invalid order option: %s' % order)
                    order = self.type_sort

                if context.req.args.has_key('desc'):
                    desc = context.req.args.get('desc') == '1'
                else:
                    desc = self.type_sort_direction
                platform_id = safe_int(context.req.args.get('type','0'))

                # Display platforms.
                req_data['order'] = order
                req_data['desc'] = desc
                req_data['type'] = self.get_type(context, platform_id)
                req_data['types'] = self.get_types(context, order, desc)

            elif action == 'types-post-add':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                type = {'name' : context.req.args.get('name'),
                        'description' : context.req.args.get('description')}

                # Add type.
                self.add_type(context, type)

            elif action == 'types-post-edit':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get form values.
                type_id = safe_int(context.req.args.get('id'))
                type = {'name' : context.req.args.get('name'),
                        'description' : context.req.args.get('description')}

                # Add platform.
                self.edit_type(context, type_id, type)

            elif action == 'types-delete':
                context.req.perm.require('DOWNLOADS_ADMIN')

                # Get selected types.
                selection = context.req.args.get('selection')
                if isinstance(selection, (str, unicode)):
                    selection = [selection]

                # Delete types.
                if selection:
                    for type_id in selection:
                        type_id = safe_int(type_id)
                        self.delete_type(context, type_id)
Example #20
0
    def _do_actions(self, context, actions):
        # Get API component.
        api = self.env[ScreenshotsApi]

        for action in actions:
            if action == 'get-file':
                context.req.perm.assert_permission('SCREENSHOTS_VIEW')

                # Get request arguments.
                screenshot_id = int(context.req.args.get('id') or 0)
                format = context.req.args.get('format') or self.default_format
                width = int(context.req.args.get('width') or 0)
                height =  int(context.req.args.get('height') or 0)

                # Check if requested format is allowed.
                if not format in self.formats:
                    raise TracError(_("Requested screenshot format that is not "
                      "allowed."), _("Requested format not allowed."))

                # Get screenshot.
                screenshot = api.get_screenshot(context, screenshot_id)

                # Check if requested screenshot exists.
                if not screenshot:
                    if context.req.perm.has_permission('SCREENSHOTS_ADD'):
                        context.req.redirect(context.req.href.screenshots(
                          action = 'add'))
                    else:
                        raise TracError(_("Screenshot not found."))

                # Set missing dimensions.
                width = width or screenshot['width']
                height = height or screenshot['height']

                if format == 'html':
                    # Format screenshot for presentation.
                    screenshot['author'] = format_to_oneliner(self.env, context,
                      screenshot['author'])
                    screenshot['name'] = format_to_oneliner(self.env, context,
                      screenshot['name'])
                    screenshot['description'] = format_to_oneliner(self.env,
                      context, screenshot['description'])
                    screenshot['time'] = pretty_timedelta(to_datetime(
                      screenshot['time'], utc))

                    # For HTML preview format return template.
                    context.req.data['screenshot'] = screenshot
                    return ('screenshot', None)
                else:
                    # Prepare screenshot filename.
                    name, ext = os.path.splitext(screenshot['file'])
                    format = (format == 'raw') and ext or '.' + format
                    path = os.path.normpath(os.path.join(self.path, to_unicode(
                      screenshot['id'])))
                    filename = os.path.normpath(os.path.join(path, '%s-%sx%s%s'
                      % (name, width, height, format)))
                    orig_name = os.path.normpath(os.path.join(path, '%s-%sx%s%s'
                      % (name, screenshot['width'], screenshot['height'], ext)))
                    base_name = os.path.normpath(os.path.basename(filename))

                    self.log.debug('filename: %s' % (filename,))

                    # Create requested file from original if not exists.
                    if not os.path.isfile(filename.encode('utf-8')):
                        self._create_image(orig_name, path, name, format,
                          width, height)

                    # Guess mime type.
                    file = open(filename.encode('utf-8'), "r")
                    file_data = file.read(1000)
                    file.close()
                    mimeview = Mimeview(self.env)
                    mime_type = mimeview.get_mimetype(filename, file_data)
                    if not mime_type:
                        mime_type = 'application/octet-stream'
                    if 'charset=' not in mime_type:
                        charset = mimeview.get_charset(file_data, mime_type)
                        mime_type = mime_type + '; charset=' + charset

                    # Send file to request.
                    context.req.send_header('Content-Disposition',
                      'attachment;filename="%s"' % (base_name))
                    context.req.send_header('Content-Description',
                      screenshot['description'])
                    context.req.send_file(filename.encode('utf-8'), mime_type)

            elif action == 'add':
                context.req.perm.assert_permission('SCREENSHOTS_ADD')

                # Get request arguments.
                index = int(context.req.args.get('index') or 0)

                # Fill data dictionary.
                context.req.data['index'] = index
                context.req.data['versions'] = api.get_versions(context)
                context.req.data['components'] = api.get_components(context)

                # Return template with add screenshot form.
                return ('screenshot-add', None)

            elif action == 'post-add':
                context.req.perm.assert_permission('SCREENSHOTS_ADD')

                # Get image file from request.
                file, filename = self._get_file_from_req(context.req)
                name, ext = os.path.splitext(filename)
                ext = ext.lower()
                filename = name + ext

                # Is uploaded file archive or single image?
                if ext == '.zip':
                    # Get global timestamp for all files in archive.
                    timestamp = to_timestamp(datetime.now(utc))

                    # List files in archive.
                    zip_file = ZipFile(file)
                    for filename in zip_file.namelist():
                        # Test file extensions for supported type.
                        name, ext = os.path.splitext(filename)
                        tmp_ext = ext.lower()[1:]
                        if tmp_ext in self.ext and tmp_ext != 'zip':
                            # Decompress image file
                            data = zip_file.read(filename)
                            file = StringIO(data)
                            filename = to_unicode(os.path.basename(filename))

                            # Screenshots must be identified by timestamp.
                            timestamp += 1

                            # Create image object.
                            image = Image.open(file)

                            # Construct screenshot dictionary from form values.
                            screenshot = {'name' :  context.req.args.get('name'),
                              'description' : context.req.args.get('description'),
                              'time' : timestamp,
                              'author' : context.req.authname,
                              'tags' : context.req.args.get('tags'),
                              'file' : filename,
                              'width' : image.size[0],
                              'height' : image.size[1],
                              'priority' : int(context.req.args.get('priority')
                              or '0')}
                            self.log.debug('screenshot: %s' % (screenshot,))

                            # Save screenshot file and add DB entry.
                            self._add_screenshot(context, api, screenshot, file)

                    zip_file.close()
                else:
                    # Create image object.
                    image = Image.open(file)

                    # Construct screenshot dictionary from form values.
                    screenshot = {'name' :  context.req.args.get('name'),
                      'description' : context.req.args.get('description'),
                      'time' : to_timestamp(datetime.now(utc)),
                      'author' : context.req.authname,
                      'tags' : context.req.args.get('tags'),
                      'file' : filename,
                      'width' : image.size[0],
                      'height' : image.size[1],
                      'priority' : int(context.req.args.get('priority')
                      or '0')}
                    self.log.debug('screenshot: %s' % (screenshot,))

                    # Add single image.
                    self._add_screenshot(context, api, screenshot, file)

                # Close input file.
                file.close()

                # Clear ID to prevent display of edit and delete button.
                context.req.args['id'] = None

            elif action == 'edit':
                context.req.perm.assert_permission('SCREENSHOTS_EDIT')

                # Get request arguments.
                screenshot_id = context.req.args.get('id')

                # Prepare data dictionary.
                context.req.data['screenshot'] = api.get_screenshot(context,
                  screenshot_id)

            elif action == 'post-edit':
                context.req.perm.assert_permission('SCREENSHOTS_EDIT')

                # Get screenshot arguments.
                screenshot_id = int(context.req.args.get('id') or 0)

                # Get old screenshot
                old_screenshot = api.get_screenshot(context, screenshot_id)

                # Check if requested screenshot exits.
                if not old_screenshot:
                    raise TracError(_("Edited screenshot not found."),
                      _("Screenshot not found."))

                # Get image file from request.
                image = context.req.args['image']
                if hasattr(image, 'filename') and image.filename:
                    in_file, filename = self._get_file_from_req(context.req)
                    name, ext = os.path.splitext(filename)
                    filename = name + ext.lower()
                else:
                    filename = None

                # Construct screenshot dictionary from form values.
                screenshot = {'name' :  context.req.args.get('name'),
                  'description' : context.req.args.get('description'),
                  'author' : context.req.authname,
                  'tags' : context.req.args.get('tags'),
                  'components' : context.req.args.get('components') or [],
                  'versions' : context.req.args.get('versions') or [],
                  'priority' : int(context.req.args.get('priority') or '0')}

                # Update dimensions and filename if image file is updated.
                if filename:
                    image = Image.open(in_file)
                    screenshot['file'] = filename
                    screenshot['width'] = image.size[0]
                    screenshot['height'] = image.size[1]

                # Convert components and versions to list if only one item is
                # selected.
                if not isinstance(screenshot['components'], list):
                     screenshot['components'] = [screenshot['components']]
                if not isinstance(screenshot['versions'], list):
                     screenshot['versions'] = [screenshot['versions']]

                self.log.debug('screenshot: %s' % (screenshot))

                # Edit screenshot.
                api.edit_screenshot(context, screenshot_id, screenshot)

                # Prepare file paths.
                if filename:
                    name, ext = os.path.splitext(screenshot['file'])
                    path = os.path.normpath(os.path.join(self.path, to_unicode(
                      screenshot_id)))
                    filepath = os.path.normpath(os.path.join(path, '%s-%ix%i%s'
                      % (name, screenshot['width'], screenshot['height'], ext)))

                    self.log.debug('path: %s' % (path,))
                    self.log.debug('filepath: %s' % (filepath,))

                    # Delete present images.
                    try:
                        for file in os.listdir(path):
                            file = os.path.normpath(os.path.join(path,
                              to_unicode(file)))
                            os.remove(file.encode('utf-8'))
                    except Exception, error:
                        raise TracError(_("Error deleting screenshot. Original "
                          "error message was: %s""") % (to_unicode(error),))

                    # Store uploaded image.
                    try:
                        out_file = open(filepath.encode('utf-8'), 'wb+') 
                        in_file.seek(0)
                        shutil.copyfileobj(in_file, out_file)
                        out_file.close()
                    except Exception, error:
                        try:
                            os.remove(filepath.encode('utf-8'))
                        except:
                            pass
                        raise TracError(_("Error storing file. Is directory "
                          "specified in path config option in [screenshots] "
                          "section of trac.ini existing? Original error "
                          "message was: %s") % (to_unicode(error),))

                # Notify change listeners.
                for listener in self.change_listeners:
                    listener.screenshot_changed(context.req, screenshot,
                      old_screenshot)

                # Clear ID to prevent display of edit and delete button.
                context.req.args['id'] = None
Example #21
0
def send_backlog_as(env, req, backlog, format):
    "This method will handle the request completely, will not return"
    mime = Mimeview(env)
    mime.send_converted(req, BACKLOG_CONVERSION_KEY, backlog, format, filename=backlog.scope)
Example #22
0
    def _do_actions(self, context, actions):

        api = TrackerApi()

        time_interval = self.env.config.getint('tracker', 'time_interval', 10)
        time_separate = 1
        minutes_interval=0
        screenshotsWithHourse = []
        screenshotsWithMinutes = []
        template_hourse = []
        minute = 0
        min_hourse = 0
        max_hourse = 0
        allScreenshots=[]

        for action in actions:
            if action == 'view':
                date = datetime.datetime.now(context.req.tz)
                if 'date' in context.req.args:
                    date_from_calendar = context.req.args['date'].strip()
                    if date_from_calendar:
                        precisedate = user_time(context.req, parse_date, date_from_calendar)
                        date = precisedate.astimezone(context.req.tz)
                to_date = to_datetime(datetime.datetime(date.year, date.month, date.day,
                                               23, 59, 59, 999999), context.req.tz)
                to_date_timestamp = to_timestamp(to_date)

                full_date = {
                    'from_date': to_date_timestamp - 86400,
                    'to_date'  : to_date_timestamp
                }

                context.req.data['fromdate'] = to_date
                context.req.data['username'] = context.req.args.get('username')

                screenshot_id = int(context.req.args.get('id') or 0)
                screenshots = api.get_screenshots(context, context.req.args.get('username'), full_date)

                context.req.data['id'] = screenshot_id

                for hourse in range(0, 24):
                    for screenshot in screenshots:
                        screenshot["hourse"] = datetime.datetime.fromtimestamp(screenshot["time"]).strftime('%H')
                        if (int(screenshot["hourse"]) == hourse):
                            if min_hourse == 0:
                                min_hourse = hourse
                            elif min_hourse > hourse:
                                min_hourse = hourse
                            if max_hourse < hourse:
                                max_hourse = hourse
                            screenshotsWithHourse.append({hourse:screenshot})

                while (minute <= 59):
                    for screenshotsAll in screenshotsWithHourse:

                        for index in screenshotsAll:

                            screenshotMinute = datetime.datetime.fromtimestamp(float(screenshotsAll[index]["time"])).strftime('%M')
                            if int(screenshotMinute) == minute:
                                screenshotHourse = datetime.datetime.fromtimestamp(screenshotsAll[index]["time"]).strftime('%H')
                                if int(screenshotHourse) not in template_hourse:
                                    template_hourse.append(int(screenshotHourse))
                                screenshotsAll[index]['hourse'] = int(screenshotHourse)
                                screenshotsAll[index]['minute'] = int(screenshotMinute)
                                if len(screenshotsWithMinutes)>0 and screenshotsWithMinutes[0]['minute']==screenshotsAll[index]['minute']:
                                    screenshotsWithMinutes.pop()
                                screenshotsWithMinutes.append(screenshotsAll[index])
                    minute += 10
                for hourse in template_hourse:
                    for screenshot in screenshotsWithMinutes:
                        if screenshot['hourse']==hourse:
                            while screenshot['minute']!=minutes_interval:
                                allScreenshots.append({"hourse":hourse,"screen":None,"minute":minutes_interval})
                                minutes_interval+=10
                            screenshot["screen"]=1
                            allScreenshots.append(screenshot)
                            minutes_interval+=10
                    while (minutes_interval!=60):
                        allScreenshots.append({"hourse":hourse,"screen":None,"minute":minutes_interval})
                        minutes_interval+=10
                    minutes_interval=0

                context.req.data['allScreenshots'] = allScreenshots
                context.req.data['template_hourse'] = range(int(min_hourse), int(max_hourse)+time_separate)
                context.req.data['time_interval'] = time_interval
                context.req.data['time_separate'] = time_separate
                context.req.data['template'] = 'user_worklog_view.html'
                add_stylesheet(context.req, 'trac/css/tracker.css')
                chrome = Chrome(self.env)
                chrome.add_jquery_ui(context.req)

                return 'screenshots', None

            if action == 'get-file':

                screenshot_id = int(context.req.args.get('id') or 0)
                format = context.req.args.get('format') or self.default_format

                screenshot = api.get_screenshot(context, screenshot_id)

                if format == 'html':
                    context.req.data['screenshot'] = screenshot
                    return 'screenshot', None
                else:
                    screenshot_path = screenshot[0]['path']
                    filename = self.path + '/' + screenshot_path

                    file = open(filename.encode('utf-8'), "r")
                    file_data = file.read(1000)
                    file.close()

                    mimeview = Mimeview(self.env)
                    mime_type = mimeview.get_mimetype(filename, file_data)
                    if not mime_type:
                        mime_type = 'application/octet-stream'
                    if 'charset=' not in mime_type:
                        charset = mimeview.get_charset(file_data, mime_type)
                        mime_type = mime_type + '; charset=' + charset

                    context.req.send_file(filename.encode('utf-8'), mime_type)
            elif action == 'get-users':

                context.req.data['users'] = api.get_users(context)
                context.req.data['template'] = 'user_list.html'
                context.req.data['client'] = {'download_href': 'jar-tracker/' + calculate_client_package_name()}
                return 'screenshots', None
            else:
                return 'screenshots', None
Example #23
0
 def mimeview_formatter(req, text):
     mimeview = Mimeview(self.env)
     context = Context.from_request(req)
     return mimeview.render(context, mimetype, text)
Example #24
0
    def _get_userlog(self, req, db, user, sort):
        mimeview = Mimeview(self.env)
        repos = self.env.get_repository()
        diff_options = get_diff_options(req)
        cursor = db.cursor()
        cursor.execute("SELECT rev, time, message FROM revision "
                       "WHERE author='%s' ORDER BY time %s" % (user, sort))
                       # Have to sort by time because rev is a text field
                       # and sorts lexicographically rather than numerically
        changesets = []
        for rev, time, message in cursor:
            if self.wiki_format_messages:
                message = wiki_to_html(message, self.env, req,
                                              escape_newlines=True)
            else:
                message = html.PRE(message)
            prev = repos.get_node('/', rev).get_previous()
            if prev:
                prev_rev = prev[1]
            else:
                prev_rev = rev
            diffs = []
            changes = repos.get_changes(old_path='/', old_rev=prev_rev,
                                        new_path='/', new_rev=rev)
            for old_node, new_node, kind, change in changes:
                if kind == Node.DIRECTORY:
                    if change == Changeset.ADD:
                        diffs.append(('%s added' % new_node.path, ''))
                    elif change == Changeset.DELETE:
                        diffs.append(('%s deleted' % old_node.path, ''))
                    continue

                new_content = old_content = ''
                new_node_info = old_node_info = ('','')
                
                if old_node:
                    old_content = old_node.get_content().read()
                    if is_binary(old_content):
                        continue
                    old_node_info = (old_node.path, old_node.rev)
                    old_content = mimeview.to_unicode(old_content,
                                                      old_node.content_type)
                if new_node:
                    new_content = new_node.get_content().read()
                    if is_binary(new_content):
                        continue
                    new_node_info = (new_node.path, new_node.rev)
                    new_path = new_node.path
                    new_content = mimeview.to_unicode(new_content,
                                                      new_node.content_type)
                else:
                    old_node_path = repos.normalize_path(old_node.path)
                    diff_old_path = repos.normalize_path('/')
                    new_path = posixpath.join('/', old_node_path[len(diff_old_path)+1:])

                if old_content != new_content:
                    context = 3
                    options = diff_options[1]
                    for option in options:
                        if option.startswith('-U'):
                            context = int(option[2:])
                            break
                    if not old_node_info[0]:
                        old_node_info = new_node_info # support for 'A'dd changes
                    diff = 'Index: ' + new_path + CRLF
                    diff += '=' * 67 + CRLF
                    diff += '--- %s (revision %s)' % old_node_info + CRLF
                    diff += '+++ %s (revision %s)' % new_node_info + CRLF
                    for line in unified_diff(old_content.splitlines(),
                                             new_content.splitlines(), context,
                                             ignore_blank_lines='-B' in options,
                                             ignore_case='-i' in options,
                                             ignore_space_changes='-b' in options):
                        diff += line + CRLF
                    if change == Changeset.ADD:
                        diffs.append(('%s added' % (new_node.path,), diff))
                    elif change == Changeset.DELETE:
                        diffs.append(('%s deleted' % (old_node.path,), diff))
                    else:
                        diffs.append(('%s edited' % (new_node.path,), diff))
            changesets.append((int(rev), format_datetime(time), message, diffs))
        return changesets
Example #25
0
    def _render_file(self, req, repos, node, rev=None):
        req.perm.assert_permission('FILE_VIEW')

        changeset = repos.get_changeset(node.rev)
        req.hdf['file'] = {
            'rev':
            node.rev,
            'changeset_href':
            util.escape(self.env.href.changeset(node.rev)),
            'date':
            time.strftime('%x %X', time.localtime(changeset.date)),
            'age':
            util.pretty_timedelta(changeset.date),
            'author':
            changeset.author or 'anonymous',
            'message':
            wiki_to_html(changeset.message or '--',
                         self.env,
                         req,
                         escape_newlines=True)
        }
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = get_mimetype(node.name) or mime_type or 'text/plain'

        # We don't have to guess if the charset is specified in the
        # svn:mime-type property
        ctpos = mime_type.find('charset=')
        if ctpos >= 0:
            charset = mime_type[ctpos + 8:]
        else:
            charset = None

        format = req.args.get('format')
        if format in ['raw', 'txt']:
            req.send_response(200)
            req.send_header('Content-Type', format == 'txt' and 'text/plain'
                            or mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified',
                            util.http_date(node.last_modified))
            req.end_headers()

            content = node.get_content()
            while 1:
                chunk = content.read(CHUNK_SIZE)
                if not chunk:
                    raise RequestDone
                req.write(chunk)

        else:
            # Generate HTML preview
            max_preview_size = int(
                self.config.get('mimeviewer', 'max_preview_size', '262144'))
            content = node.get_content().read(max_preview_size)
            max_size_reached = len(content) == max_preview_size
            if not charset:
                charset = detect_unicode(content) or \
                          self.config.get('trac', 'default_charset')
            if not is_binary(content):
                content = util.to_utf8(content, charset)
                if mime_type != 'text/plain':
                    plain_href = self.env.href.browser(node.path,
                                                       rev=rev and node.rev,
                                                       format='txt')
                    add_link(req, 'alternate', plain_href, 'Plain Text',
                             'text/plain')
            if max_size_reached:
                req.hdf['file.max_file_size_reached'] = 1
                req.hdf['file.max_file_size'] = max_preview_size
                preview = ' '
            else:
                preview = Mimeview(self.env).render(req,
                                                    mime_type,
                                                    content,
                                                    node.name,
                                                    node.rev,
                                                    annotations=['lineno'])
            req.hdf['file.preview'] = preview

            raw_href = self.env.href.browser(node.path,
                                             rev=rev and node.rev,
                                             format='raw')
            req.hdf['file.raw_href'] = util.escape(raw_href)
            add_link(req, 'alternate', raw_href, 'Original Format', mime_type)

            add_stylesheet(req, 'common/css/code.css')
Example #26
0
    def render_admin_panel(self, req, cat, page, version):
        # here comes the page content, handling, etc.
        data = {}

        if req.method == "POST":
            submit = req.args.get('submit').strip()
            if submit == 'Add':
                # Get form values.
                #file = req.args['download']
                # Test if file is uploaded.
                #if hasattr(file, 'filename'):
                #    self.log.debug("Filename:" + file.filename)

                file, filename, file_size = self.get_file_from_req(req)
                download = {
                    'file': filename,
                    'description': req.args.get('description'),
                    'size': file_size,
                    'time': to_timestamp(datetime.datetime.now(utc)),
                    'count': 0,
                    'author': req.authname
                }
                self.log.debug("FileUpload filename:" + download['file'])
                self.log.debug("FileUpload description:" +
                               download['description'])
                self.log.debug("FileUpload size:", download['size'])
                self.log.debug("FileUpload time:", download['time'])
                self.log.debug("FileUpload author:" + download['author'])
                # Upload file to DB and file storage.
                add_download(download, file)
                file.close()

                add_notice(req, 'Download has been added.')
            elif submit == 'Remove':
                ids = req.args.getlist('sels')
                if ids is not None and len(ids) > 0:
                    for id in ids:
                        sql = "DELETE FROM download WHERE id ={}".format(
                            int(id))
                        self.env.db_transaction(sql)
                    add_notice(req, 'Download has been deleted.')
        else:
            # Get download.
            download_id = req.args.get('sel') or 0
            if download_id > 0:
                sql = "SELECT file, description FROM download where id={}".format(
                    download_id)
                cursor = self.env.db_query(sql)
                if len(cursor) > 0:
                    fn = cursor[0][0]
                    description = cursor[0][1]
                else:
                    raise TracError("File not found.")

                # Get download file path.
                filename = os.path.basename(fn)
                filepath = os.path.join(self.path, to_unicode(download_id),
                                        filename)
                filepath = os.path.normpath(filepath)

                # Increase downloads count.
                sql = "UPDATE download SET count=count+1 WHERE id ={}".format(
                    download_id)
                self.env.db_transaction(sql)

                # Guess mime type.
                with open(filepath.encode('utf-8'), 'r') as fileobj:
                    file_data = fileobj.read(1000)
                mimeview = Mimeview(self.env)
                mime_type = mimeview.get_mimetype(filepath, file_data)
                if not mime_type:
                    mime_type = 'application/octet-stream'
                if 'charset=' not in mime_type:
                    charset = mimeview.get_charset(file_data, mime_type)
                    mime_type = mime_type + '; charset=' + charset

                # Return uploaded file to request.
                req.send_header(
                    'Content-Disposition',
                    'attachment;filename="%s"' % os.path.normpath(fn))
                req.send_header('Content-Description', description)
                req.send_file(filepath.encode('utf-8'), mime_type)

        cursor = self.env.db_query(
            "SELECT id, file, description, size, time, author FROM download ORDER BY id"
        )
        data['downloads'] = [(row[0], row[1], row[2]) for row in cursor]
        return ('admin_download.html', data, None)
Example #27
0
 def mimeview_formatter(req, text):
     mimeview = Mimeview(self.env)
     context = Context.from_request(req)
     return mimeview.render(context, mimetype, text)
Example #28
0
    def _do_actions(self, context, actions):

        api = TrackerApi()

        time_interval = self.env.config.getint('tracker', 'time_interval', 10)
        time_separate = 1
        minutes_interval = 0
        screenshotsWithHourse = []
        screenshotsWithMinutes = []
        template_hourse = []
        minute = 0
        min_hourse = 0
        max_hourse = 0
        allScreenshots = []

        for action in actions:
            if action == 'view':
                date = datetime.datetime.now(context.req.tz)
                if 'date' in context.req.args:
                    date_from_calendar = context.req.args['date'].strip()
                    if date_from_calendar:
                        precisedate = user_time(context.req, parse_date,
                                                date_from_calendar)
                        date = precisedate.astimezone(context.req.tz)
                to_date = to_datetime(
                    datetime.datetime(date.year, date.month, date.day, 23, 59,
                                      59, 999999), context.req.tz)
                to_date_timestamp = to_timestamp(to_date)

                full_date = {
                    'from_date': to_date_timestamp - 86400,
                    'to_date': to_date_timestamp
                }

                context.req.data['fromdate'] = to_date
                context.req.data['username'] = context.req.args.get('username')

                screenshot_id = int(context.req.args.get('id') or 0)
                screenshots = api.get_screenshots(
                    context, context.req.args.get('username'), full_date)

                context.req.data['id'] = screenshot_id

                for hourse in range(0, 24):
                    for screenshot in screenshots:
                        screenshot["hourse"] = datetime.datetime.fromtimestamp(
                            screenshot["time"]).strftime('%H')
                        if (int(screenshot["hourse"]) == hourse):
                            if min_hourse == 0:
                                min_hourse = hourse
                            elif min_hourse > hourse:
                                min_hourse = hourse
                            if max_hourse < hourse:
                                max_hourse = hourse
                            screenshotsWithHourse.append({hourse: screenshot})

                while (minute <= 59):
                    for screenshotsAll in screenshotsWithHourse:

                        for index in screenshotsAll:

                            screenshotMinute = datetime.datetime.fromtimestamp(
                                float(screenshotsAll[index]["time"])).strftime(
                                    '%M')
                            if int(screenshotMinute) == minute:
                                screenshotHourse = datetime.datetime.fromtimestamp(
                                    screenshotsAll[index]["time"]).strftime(
                                        '%H')
                                if int(screenshotHourse
                                       ) not in template_hourse:
                                    template_hourse.append(
                                        int(screenshotHourse))
                                screenshotsAll[index]['hourse'] = int(
                                    screenshotHourse)
                                screenshotsAll[index]['minute'] = int(
                                    screenshotMinute)
                                if len(screenshotsWithMinutes
                                       ) > 0 and screenshotsWithMinutes[0][
                                           'minute'] == screenshotsAll[index][
                                               'minute']:
                                    screenshotsWithMinutes.pop()
                                screenshotsWithMinutes.append(
                                    screenshotsAll[index])
                    minute += 10
                for hourse in template_hourse:
                    for screenshot in screenshotsWithMinutes:
                        if screenshot['hourse'] == hourse:
                            while screenshot['minute'] != minutes_interval:
                                allScreenshots.append({
                                    "hourse":
                                    hourse,
                                    "screen":
                                    None,
                                    "minute":
                                    minutes_interval
                                })
                                minutes_interval += 10
                            screenshot["screen"] = 1
                            allScreenshots.append(screenshot)
                            minutes_interval += 10
                    while (minutes_interval != 60):
                        allScreenshots.append({
                            "hourse": hourse,
                            "screen": None,
                            "minute": minutes_interval
                        })
                        minutes_interval += 10
                    minutes_interval = 0

                context.req.data['allScreenshots'] = allScreenshots
                context.req.data['template_hourse'] = range(
                    int(min_hourse),
                    int(max_hourse) + time_separate)
                context.req.data['time_interval'] = time_interval
                context.req.data['time_separate'] = time_separate
                context.req.data['template'] = 'user_worklog_view.html'
                add_stylesheet(context.req, 'trac/css/tracker.css')
                chrome = Chrome(self.env)
                chrome.add_jquery_ui(context.req)

                return 'screenshots', None

            if action == 'get-file':

                screenshot_id = int(context.req.args.get('id') or 0)
                format = context.req.args.get('format') or self.default_format

                screenshot = api.get_screenshot(context, screenshot_id)

                if format == 'html':
                    context.req.data['screenshot'] = screenshot
                    return 'screenshot', None
                else:
                    screenshot_path = screenshot[0]['path']
                    filename = self.path + '/' + screenshot_path

                    file = open(filename.encode('utf-8'), "r")
                    file_data = file.read(1000)
                    file.close()

                    mimeview = Mimeview(self.env)
                    mime_type = mimeview.get_mimetype(filename, file_data)
                    if not mime_type:
                        mime_type = 'application/octet-stream'
                    if 'charset=' not in mime_type:
                        charset = mimeview.get_charset(file_data, mime_type)
                        mime_type = mime_type + '; charset=' + charset

                    context.req.send_file(filename.encode('utf-8'), mime_type)
            elif action == 'get-users':

                context.req.data['users'] = api.get_users(context)
                context.req.data['template'] = 'user_list.html'
                context.req.data['client'] = {
                    'download_href':
                    'jar-tracker/' + calculate_client_package_name()
                }
                return 'screenshots', None
            else:
                return 'screenshots', None
Example #29
0
    def _render_file(self, req, repos, node, rev=None):
        req.perm.assert_permission('FILE_VIEW')

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = mimeview.get_mimetype(node.name, chunk) or \
                        mime_type or 'text/plain'

        # Eventually send the file directly
        format = req.args.get('format')
        if format in ['raw', 'txt']:
            req.send_response(200)
            req.send_header('Content-Type', format == 'txt' and 'text/plain'
                            or mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified', http_date(node.last_modified))
            if not self.render_unsafe_content:
                # Force browser to download files instead of rendering
                # them, since they might contain malicious code enabling
                # XSS attacks
                req.send_header('Content-Disposition', 'attachment')
            req.end_headers()

            while 1:
                if not chunk:
                    raise RequestDone
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
        else:
            # The changeset corresponding to the last change on `node`
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.rev)

            message = changeset.message or '--'
            if self.config['changeset'].getbool('wiki_format_messages'):
                message = wiki_to_html(message,
                                       self.env,
                                       req,
                                       escape_newlines=True)
            else:
                message = html.PRE(message)
            ZhUnit = {
                'second': u'秒',
                'seconds': u'秒',
                'minute': u'分钟',
                'minutes': u'分钟',
                'hour': u'小时',
                'hours': u'小时',
                'day': u'天',
                'days': u'天',
                'year': u'年',
                'years': u'年',
                'month': u'月',
                'months': u'月'
            }
            tempTime = pretty_timedelta(changeset.date)
            numAndUnit = tempTime.split(' ')
            numAndUnit[1] = ZhUnit.get(numAndUnit[1], numAndUnit[1])
            ZhAge = ' '.join(numAndUnit)
            req.hdf['file'] = {
                'rev': node.rev,
                'changeset_href': req.href.changeset(node.rev),
                'date': format_datetime(changeset.date),
                'age': ZhAge,
                'size': pretty_size(node.content_length),
                'author': changeset.author or 'anonymous',
                'message': message
            }

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != 'text/plain':
                plain_href = req.href.browser(node.path, rev=rev, format='txt')
                add_link(req, 'alternate', plain_href, 'Plain Text',
                         'text/plain')

            # add ''Original Format'' alternate link (always)
            raw_href = req.href.browser(node.path, rev=rev, format='raw')
            add_link(req, 'alternate', raw_href, 'Original Format', mime_type)

            self.log.debug(
                "Rendering preview of node %s@%s with mime-type %s" %
                (node.name, str(rev), mime_type))

            del content  # the remainder of that content is not needed

            req.hdf['file'] = mimeview.preview_to_hdf(
                req,
                node.get_content(),
                node.get_content_length(),
                mime_type,
                node.created_path,
                raw_href,
                annotations=['lineno'])

            add_stylesheet(req, 'common/css/code.css')
Example #30
0
    def _render_diff(self, req, filename, repos, data):
        """Raw Unified Diff version"""
        req.send_response(200)
        req.send_header('Content-Type', 'text/x-patch;charset=utf-8')
        req.send_header('Content-Disposition',
                        content_disposition('inline', filename + '.diff'))
        buf = StringIO()
        mimeview = Mimeview(self.env)

        for old_node, new_node, kind, change in repos.get_changes(
            new_path=data['new_path'], new_rev=data['new_rev'],
            old_path=data['old_path'], old_rev=data['old_rev']):
            # TODO: Property changes

            # Content changes
            if kind == Node.DIRECTORY:
                continue

            new_content = old_content = ''
            new_node_info = old_node_info = ('','')
            mimeview = Mimeview(self.env)

            if old_node:
                if mimeview.is_binary(old_node.content_type, old_node.path):
                    continue
                old_content = old_node.get_content().read()
                if mimeview.is_binary(content=old_content):
                    continue
                old_node_info = (old_node.path, old_node.rev)
                old_content = mimeview.to_unicode(old_content,
                                                  old_node.content_type)
            if new_node:
                if mimeview.is_binary(new_node.content_type, new_node.path):
                    continue
                new_content = new_node.get_content().read()
                if mimeview.is_binary(content=new_content):
                    continue
                new_node_info = (new_node.path, new_node.rev)
                new_path = new_node.path
                new_content = mimeview.to_unicode(new_content,
                                                  new_node.content_type)
            else:
                old_node_path = repos.normalize_path(old_node.path)
                diff_old_path = repos.normalize_path(data['old_path'])
                new_path = posixpath.join(data['new_path'],
                                          old_node_path[len(diff_old_path)+1:])

            if old_content != new_content:
                options = data['diff']['options']
                context = options.get('contextlines', 3)
                if context < 0:
                    context = 3 # FIXME: unified_diff bugs with context=None
                ignore_blank_lines = options.get('ignoreblanklines')
                ignore_case = options.get('ignorecase')
                ignore_space = options.get('ignorewhitespace')
                if not old_node_info[0]:
                    old_node_info = new_node_info # support for 'A'dd changes
                buf.write('Index: ' + new_path + CRLF)
                buf.write('=' * 67 + CRLF)
                buf.write('--- %s\t(revision %s)' % old_node_info + CRLF)
                buf.write('+++ %s\t(revision %s)' % new_node_info + CRLF)
                for line in unified_diff(old_content.splitlines(),
                                         new_content.splitlines(), context,
                                         ignore_blank_lines=ignore_blank_lines,
                                         ignore_case=ignore_case,
                                         ignore_space_changes=ignore_space):
                    buf.write(line + CRLF)
                    
        diff_str = buf.getvalue().encode('utf-8')
        req.send_header('Content-Length', len(diff_str))
        req.end_headers()
        req.write(diff_str)
        raise RequestDone
Example #31
0
 def mimeview_formatter(req, text):
     mimeview = Mimeview(self.env)
     context = web_context(req)
     return mimeview.render(context, mimetype, text)
Example #32
0
    def _render_file(self, req, repos, node, rev=None):
        req.perm.assert_permission('FILE_VIEW')

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = mimeview.get_mimetype(node.name, chunk) or \
                        mime_type or 'text/plain'

        # Eventually send the file directly
        format = req.args.get('format')
        if format in ['raw', 'txt']:
            req.send_response(200)
            req.send_header('Content-Type',
                            format == 'txt' and 'text/plain' or mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified', http_date(node.last_modified))
            req.end_headers()

            while 1:
                if not chunk:
                    raise RequestDone
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
        else:
            # The changeset corresponding to the last change on `node` 
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.rev)

            message = changeset.message or '--'
            if self.config['changeset'].getbool('wiki_format_messages'):
                message = wiki_to_html(message, self.env, req,
                                       escape_newlines=True)
            else:
                message = html.PRE(message)

            req.hdf['file'] = {
                'rev': node.rev,
                'changeset_href': req.href.changeset(node.rev),
                'date': format_datetime(changeset.date),
                'age': pretty_timedelta(changeset.date),
                'size': pretty_size(node.content_length),
                'author': changeset.author or 'anonymous',
                'message': message
            } 

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != 'text/plain':
                plain_href = req.href.browser(node.path, rev=rev, format='txt')
                add_link(req, 'alternate', plain_href, 'Plain Text',
                         'text/plain')

            # add ''Original Format'' alternate link (always)
            raw_href = req.href.browser(node.path, rev=rev, format='raw')
            add_link(req, 'alternate', raw_href, u'Format original', mime_type)

            self.log.debug("Rendering preview of node %s@%s with mime-type %s"
                           % (node.name, str(rev), mime_type))

            del content # the remainder of that content is not needed

            req.hdf['file'] = mimeview.preview_to_hdf(
                req, node.get_content(), node.get_content_length(), mime_type,
                node.created_path, raw_href, annotations=['lineno'])

            add_stylesheet(req, 'common/css/code.css')