Esempio n. 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)
Esempio n. 2
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)
Esempio n. 3
0
    def validate_attachment(self, req, attachment):
        if 'WIKI_ADMIN' in req.perm:
            # An administrator is allowed to spam
            return []

        author = req.args.get('author', req.authname)
        description = req.args.get('description')

        filename = None
        upload = req.args.get('attachment')
        content = ''
        if upload is not None:
            try:
                data = upload.file.read(self.sample_size)
                if not is_binary(data):
                    content = to_unicode(data)
            finally:
                upload.file.seek(0)
            filename = upload.filename

        changes = []
        for field in filter(None, [description, filename, content]):
            changes += [(None, field)]

        FilterSystem(self.env).test(req, author, changes)
        return []
Esempio n. 4
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 []
Esempio n. 5
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 []
Esempio n. 6
0
    def _render_diff(self, req, repos, chgset, 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',
                        'filename=Changeset%s.diff' % req.args.get('rev'))
        req.end_headers()

        for path, kind, change, base_path, base_rev in chgset.get_changes():
            if change == Changeset.ADD:
                old_node = None
            else:
                old_node = repos.get_node(base_path or path, base_rev)
            if change == Changeset.DELETE:
                new_node = None
            else:
                new_node = repos.get_node(path, chgset.rev)

            # TODO: Property changes

            # Content changes
            if kind == 'dir':
                continue

            default_charset = self.config.get('trac', 'default_charset')
            new_content = old_content = ''
            new_node_info = old_node_info = ('', '')

            if old_node:
                charset = mimeview.get_charset(old_node.content_type) or \
                          default_charset
                old_content = util.to_utf8(old_node.get_content().read(),
                                           charset)
                old_node_info = (old_node.path, old_node.rev)
            if mimeview.is_binary(old_content):
                continue

            if new_node:
                charset = mimeview.get_charset(new_node.content_type) or \
                          default_charset
                new_content = util.to_utf8(new_node.get_content().read(),
                                           charset)
                new_node_info = (new_node.path, new_node.rev)
            if mimeview.is_binary(new_content):
                continue

            if old_content != new_content:
                context = 3
                for option in diff_options[1]:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                req.write('Index: ' + path + util.CRLF)
                req.write('=' * 67 + util.CRLF)
                req.write('--- %s (revision %s)' % old_node_info + util.CRLF)
                req.write('+++ %s (revision %s)' % new_node_info + util.CRLF)
                for line in unified_diff(old_content.splitlines(),
                                         new_content.splitlines(),
                                         context,
                                         ignore_blank_lines='-B'
                                         in diff_options[1],
                                         ignore_case='-i' in diff_options[1],
                                         ignore_space_changes='-b'
                                         in diff_options[1]):
                    req.write(line + util.CRLF)
Esempio n. 7
0
    def _render_html(self, req, repos, chgset, diff_options):
        """HTML version"""
        req.hdf['title'] = '[%s]' % chgset.rev
        req.hdf['changeset'] = {
            'revision':
            chgset.rev,
            'time':
            time.strftime('%c', time.localtime(chgset.date)),
            'author':
            util.escape(chgset.author or 'anonymous'),
            'message':
            wiki_to_html(chgset.message or '--',
                         self.env,
                         req,
                         escape_newlines=True)
        }

        oldest_rev = repos.oldest_rev
        if chgset.rev != oldest_rev:
            add_link(req, 'first', self.env.href.changeset(oldest_rev),
                     'Changeset %s' % oldest_rev)
            previous_rev = repos.previous_rev(chgset.rev)
            add_link(req, 'prev', self.env.href.changeset(previous_rev),
                     'Changeset %s' % previous_rev)
        youngest_rev = repos.youngest_rev
        if str(chgset.rev) != str(youngest_rev):
            next_rev = repos.next_rev(chgset.rev)
            add_link(req, 'next', self.env.href.changeset(next_rev),
                     'Changeset %s' % next_rev)
            add_link(req, 'last', self.env.href.changeset(youngest_rev),
                     'Changeset %s' % youngest_rev)

        edits = []
        idx = 0
        for path, kind, change, base_path, base_rev in chgset.get_changes():
            info = {'change': change}
            if base_path:
                info['path.old'] = base_path
                info['rev.old'] = base_rev
                info['browser_href.old'] = self.env.href.browser(base_path,
                                                                 rev=base_rev)
            if path:
                info['path.new'] = path
                info['rev.new'] = chgset.rev
                info['browser_href.new'] = self.env.href.browser(
                    path, rev=chgset.rev)
            if change in (Changeset.COPY, Changeset.EDIT, Changeset.MOVE):
                edits.append((idx, path, kind, base_path, base_rev))
            req.hdf['changeset.changes.%d' % idx] = info
            idx += 1

        hidden_properties = [
            p.strip() for p in self.config.get('browser', 'hide_properties',
                                               'svk:merge').split(',')
        ]

        for idx, path, kind, base_path, base_rev in edits:
            old_node = repos.get_node(base_path or path, base_rev)
            new_node = repos.get_node(path, chgset.rev)

            # Property changes
            old_props = old_node.get_properties()
            new_props = new_node.get_properties()
            changed_props = {}
            if old_props != new_props:
                for k, v in old_props.items():
                    if not k in new_props:
                        changed_props[k] = {'old': v}
                    elif v != new_props[k]:
                        changed_props[k] = {'old': v, 'new': new_props[k]}
                for k, v in new_props.items():
                    if not k in old_props:
                        changed_props[k] = {'new': v}
                for k in hidden_properties:
                    if k in changed_props:
                        del changed_props[k]
                req.hdf['changeset.changes.%d.props' % idx] = changed_props

            if kind == Node.DIRECTORY:
                continue

            # Content changes
            default_charset = self.config.get('trac', 'default_charset')
            old_content = old_node.get_content().read()
            if mimeview.is_binary(old_content):
                continue
            charset = mimeview.get_charset(old_node.content_type) or \
                      default_charset
            old_content = util.to_utf8(old_content, charset)

            new_content = new_node.get_content().read()
            if mimeview.is_binary(new_content):
                continue
            charset = mimeview.get_charset(new_node.content_type) or \
                      default_charset
            new_content = util.to_utf8(new_content, charset)

            if old_content != new_content:
                context = 3
                for option in diff_options[1]:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                tabwidth = int(
                    self.config.get('diff', 'tab_width',
                                    self.config.get('mimeviewer',
                                                    'tab_width')))
                changes = hdf_diff(old_content.splitlines(),
                                   new_content.splitlines(),
                                   context,
                                   tabwidth,
                                   ignore_blank_lines='-B' in diff_options[1],
                                   ignore_case='-i' in diff_options[1],
                                   ignore_space_changes='-b'
                                   in diff_options[1])
                req.hdf['changeset.changes.%d.diff' % idx] = changes
Esempio n. 8
0
    def _render_diff(self, req, repos, chgset, 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=Changeset%s.diff' % chgset.rev)
        req.end_headers()

        for path, kind, change, base_path, base_rev in chgset.get_changes():
            if change == Changeset.ADD:
                old_node = None
            else:
                old_node = repos.get_node(base_path or path, base_rev)
            if change == Changeset.DELETE:
                new_node = None
            else:
                new_node = repos.get_node(path, chgset.rev)

            # TODO: Property changes

            # Content changes
            if kind == 'dir':
                continue

            default_charset = self.config.get('trac', 'default_charset')
            new_content = old_content = ''
            new_node_info = old_node_info = ('','')

            if old_node:
                charset = mimeview.get_charset(old_node.content_type) or \
                          default_charset
                old_content = util.to_utf8(old_node.get_content().read(),
                                           charset)
                old_node_info = (old_node.path, old_node.rev)
            if mimeview.is_binary(old_content):
                continue

            if new_node:
                charset = mimeview.get_charset(new_node.content_type) or \
                          default_charset
                new_content = util.to_utf8(new_node.get_content().read(),
                                           charset)
                new_node_info = (new_node.path, new_node.rev)
            if mimeview.is_binary(new_content):
                continue

            if old_content != new_content:
                context = 3
                for option in diff_options[1]:
                    if option.startswith('-U'):
                        context = int(option[2:])
                        break
                req.write('Index: ' + path + util.CRLF)
                req.write('=' * 67 + util.CRLF)
                req.write('--- %s (revision %s)' % old_node_info +
                          util.CRLF)
                req.write('+++ %s (revision %s)' % new_node_info +
                          util.CRLF)
                for line in unified_diff(old_content.splitlines(),
                                         new_content.splitlines(), context,
                                         ignore_blank_lines='-B' in diff_options[1],
                                         ignore_case='-i' in diff_options[1],
                                         ignore_space_changes='-b' in diff_options[1]):
                    req.write(line + util.CRLF)
Esempio n. 9
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')
Esempio n. 10
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')
Esempio n. 11
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')
Esempio n. 12
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
Esempio n. 13
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')
Esempio n. 14
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')