Example #1
0
    def process_request(self, req):
        stylespec = (req.args.get('ss_mod'), req.args.get('ss_id'), req.args.get('ss_fil'))
        docspec   = (req.args.get('doc_mod'), req.args.get('doc_id'), req.args.get('doc_fil'))
        if None in stylespec or None in docspec:
            self.env.log.error("Missing request parameters: %s", req.args)
            raise TracError('Bad request')

        style_obj = self._get_src(self.env, req, *stylespec)
        doc_obj   = self._get_src(self.env, req, *docspec)
        params    = dict(self._get_opts(req.args, 'xp_'))

        lastmod = max(style_obj.get_last_modified(),
                      doc_obj.get_last_modified())

        req.check_modified(lastmod)
        if not req.get_header('If-None-Match'):
            if http_date(lastmod) == req.get_header('If-Modified-Since'):
                req.send_response(304)
                req.end_headers()
                raise RequestDone
        req.send_header('Last-Modified', http_date(lastmod))

        page, content_type = self._transform(style_obj, doc_obj, params, self.env, req)

        req.send_response(200)
        req.send_header('Content-Type', content_type + ';charset=utf-8')
        req.send_header('Content-Length', len(page))
        req.end_headers()

        if req.method != 'HEAD':
            req.write(page)

        raise RequestDone
def process_request(plugin, req):
    """Renders a svg graph based on request attributes and returns a http response (or traceback in case of error)"""
    class MyDebug:
        out = ""
        def write(self, data):
            self.out += data

    import tractimevisualizerplugin
    debug = None;
    if tractimevisualizerplugin.DEVELOPER_MODE:
        debug = MyDebug()
    try:
        from trac.web import RequestDone
        from trac.util.datefmt import http_date
        from time import time

        req.send_response(200)
        req.send_header('Content-Type', "image/svg+xml")
        req.send_header('Last-Modified', http_date(time()))
        req.end_headers()

        if req.method != 'HEAD':
            db = plugin.env.get_db_cnx()
            req.write(build_svg(db, req.args, debug))
        raise RequestDone
    finally:
        if debug:
            plugin.log.debug(debug.out)
Example #3
0
    def check_modified(self, datetime, extra=''):
        """Check the request "If-None-Match" header against an entity tag.

        The entity tag is generated from the specified last modified time
        (`datetime`), optionally appending an `extra` string to
        indicate variants of the requested resource.

        That `extra` parameter can also be a list, in which case the MD5 sum
        of the list content will be used.

        If the generated tag matches the "If-None-Match" header of the request,
        this method sends a "304 Not Modified" response to the client.
        Otherwise, it adds the entity tag as an "ETag" header to the response
        so that consecutive requests can be cached.
        """
        if isinstance(extra, list):
            m = md5()
            for elt in extra:
                m.update(repr(elt))
            extra = m.hexdigest()
        etag = 'W/"%s/%s/%s"' % (self.authname, http_date(datetime), extra)
        inm = self.get_header('If-None-Match')
        if not inm or inm != etag:
            self.send_header('ETag', etag)
        else:
            self.send_response(304)
            self.send_header('Content-Length', 0)
            self.end_headers()
            raise RequestDone
Example #4
0
def process_request(plugin, req):
    """Renders a svg graph based on request attributes and returns a http response (or traceback in case of error)"""
    class MyDebug:
        out = ""

        def write(self, data):
            self.out += data

    import tractimevisualizerplugin
    debug = None
    if tractimevisualizerplugin.DEVELOPER_MODE:
        debug = MyDebug()
    try:
        #print>>debug, dir(req)
        from trac.web import RequestDone
        from trac.util.datefmt import http_date
        from time import time

        req.send_response(200)
        req.send_header('Content-Type', "image/svg+xml")
        req.send_header('Last-Modified', http_date(time()))
        req.end_headers()

        if req.method != 'HEAD':
            db = plugin.env.get_db_cnx()
            args = req.args.copy()
            args['calc_fields'] = plugin.env.config.get(
                'timevisualizer', 'calc_fields', 'estimatedhours-totalhours')
            req.write(build_svg(db, args, debug))
        raise RequestDone
    finally:
        if debug:
            plugin.log.debug(debug.out)
Example #5
0
    def check_modified(self, datetime, extra=''):
        """Check the request "If-None-Match" header against an entity tag.

        The entity tag is generated from the specified last modified time
        (`datetime`), optionally appending an `extra` string to
        indicate variants of the requested resource.

        That `extra` parameter can also be a list, in which case the MD5 sum
        of the list content will be used.

        If the generated tag matches the "If-None-Match" header of the request,
        this method sends a "304 Not Modified" response to the client.
        Otherwise, it adds the entity tag as an "ETag" header to the response
        so that consecutive requests can be cached.
        """
        if isinstance(extra, list):
            m = md5()
            for elt in extra:
                m.update(repr(elt))
            extra = m.hexdigest()
        etag = 'W/"%s/%s/%s"' % (self.authname, http_date(datetime), extra)
        inm = self.get_header('If-None-Match')
        if (not inm or inm != etag):
            self.send_header('ETag', etag)
        else:
            self.send_response(304)
            self.send_header('Content-Length', 0)
            self.end_headers()
            raise RequestDone
Example #6
0
 def export_rss(self, req, query):
     query.verbose = True
     db = self.env.get_db_cnx()
     results = query.execute(req, db)
     for result in results:
         result['href'] = req.abs_href.ticket(result['id'])
         if result['reporter'].find('@') == -1:
             result['reporter'] = ''
         if result['description']:
             # unicode() cancels out the Markup() returned by wiki_to_html
             descr = wiki_to_html(result['description'],
                                  self.env,
                                  req,
                                  db,
                                  absurls=True)
             result['description'] = unicode(descr)
         if result['time']:
             result['time'] = http_date(result['time'])
     req.hdf['query.results'] = results
     req.hdf['query.href'] = req.abs_href.query(
         group=query.group,
         groupdesc=query.groupdesc and 1 or None,
         verbose=query.verbose and 1 or None,
         **query.constraints)
     return (req.hdf.render('query_rss.cs'), 'application/rss+xml')
Example #7
0
    def send_file(self, path, mimetype=None):
        """Send a local file to the browser.
        
        This method includes the "Last-Modified", "Content-Type" and
        "Content-Length" headers in the response, corresponding to the file
        attributes. It also checks the last modification time of the local file
        against the "If-Modified-Since" provided by the user agent, and sends a
        "304 Not Modified" response if it matches.
        """
        if not os.path.isfile(path):
            raise HTTPNotFound("File %s not found" % path)

        stat = os.stat(path)
        last_modified = http_date(stat.st_mtime)
        if last_modified == self.get_header('If-Modified-Since'):
            self.send_response(304)
            self.end_headers()
            raise RequestDone

        if not mimetype:
            mimetype = mimetypes.guess_type(path)[0] or \
                       'application/octet-stream'

        self.send_response(200)
        self.send_header('Content-Type', mimetype)
        self.send_header('Content-Length', stat.st_size)
        self.send_header('Last-Modified', last_modified)
        self.end_headers()

        if self.method != 'HEAD':
            self._response = file(path, 'rb')
            file_wrapper = self.environ.get('wsgi.file_wrapper')
            if file_wrapper:
                self._response = file_wrapper(self._response, 4096)
        raise RequestDone
Example #8
0
    def process_request(self, req):
        style = req.args['style']
        try:
            style_cls = get_style_by_name(style)
        except ValueError as e:
            raise HTTPNotFound(e)

        parts = style_cls.__module__.split('.')
        filename = resource_filename('.'.join(parts[:-1]), parts[-1] + '.py')
        mtime = datetime.fromtimestamp(os.path.getmtime(filename), localtz)
        last_modified = http_date(mtime)
        if last_modified == req.get_header('If-Modified-Since'):
            req.send_response(304)
            req.end_headers()
            return

        formatter = HtmlFormatter(style=style_cls)
        content = u'\n\n'.join([
            formatter.get_style_defs('div.code pre'),
            formatter.get_style_defs('table.code td')
        ]).encode('utf-8')

        req.send_response(200)
        req.send_header('Content-Type', 'text/css; charset=utf-8')
        req.send_header('Last-Modified', last_modified)
        req.send_header('Content-Length', len(content))
        req.write(content)
Example #9
0
    def process_request(self, req):
        style = req.args['style']
        try:
            style_cls = get_style_by_name(style)
        except ValueError as e:
            raise HTTPNotFound(e)

        parts = style_cls.__module__.split('.')
        filename = resource_filename('.'.join(parts[:-1]), parts[-1] + '.py')
        mtime = datetime.fromtimestamp(os.path.getmtime(filename), localtz)
        last_modified = http_date(mtime)
        if last_modified == req.get_header('If-Modified-Since'):
            req.send_response(304)
            req.end_headers()
            return

        formatter = HtmlFormatter(style=style_cls)
        content = u'\n\n'.join([
            formatter.get_style_defs('div.code pre'),
            formatter.get_style_defs('table.code td')
        ]).encode('utf-8')

        req.send_response(200)
        req.send_header('Content-Type', 'text/css; charset=utf-8')
        req.send_header('Last-Modified', last_modified)
        req.send_header('Content-Length', len(content))
        req.write(content)
Example #10
0
    def runTest(self):
        """Test timeline in RSS format."""
        pagename = random_unique_camel()
        self._tester.create_wiki_page(pagename)
        page = WikiPage(self._testenv.get_trac_environment(), pagename)
        self._tester.go_to_timeline()
        tc.follow("RSS Feed")
        tc.find(
            r"""<\?xml version="1.0"\?>[\n]+
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Functional Tests</title>
    <link>http://127.0.0.1:\d+/timeline</link>
    <description>Trac Timeline</description>
    <language>en-US</language>
    <generator>Trac [^<]+</generator>
    <image>
      <title>Functional Tests</title>
      <url>http://127.0.0.1:\d+/chrome/site/your_project_logo.png</url>
      <link>http://127.0.0.1:\d+/timeline</link>
    </image>
    <item>
      <title>%(pagename)s created</title>

      <dc:creator>admin</dc:creator>
      <pubDate>%(http_date)s</pubDate>
      <link>http://127.0.0.1:\d+/wiki/%(pagename)s\?version=1</link>
      <guid isPermaLink="false">http://127.0.0.1:\d+/wiki/%(pagename)s\?version=1/\d+</guid>
      <description>[^<]+</description>
      <category>wiki</category>
    </item>
""" % {
                'pagename': pagename,
                'http_date': http_date(page.time)
            }, 'ms')
Example #11
0
    def send_file(self, path, mimetype=None):
        """Send a local file to the browser.
        
        This method includes the "Last-Modified", "Content-Type" and
        "Content-Length" headers in the response, corresponding to the file
        attributes. It also checks the last modification time of the local file
        against the "If-Modified-Since" provided by the user agent, and sends a
        "304 Not Modified" response if it matches.
        """
        if not os.path.isfile(path):
            raise HTTPNotFound(u"Fichier %s non trouvé" % path)

        stat = os.stat(path)
        last_modified = http_date(stat.st_mtime)
        if last_modified == self.get_header('If-Modified-Since'):
            self.send_response(304)
            self.end_headers()
            raise RequestDone

        if not mimetype:
            mimetype = mimetypes.guess_type(path)[0] or \
                       'application/octet-stream'

        self.send_response(200)
        self.send_header('Content-Type', mimetype)
        self.send_header('Content-Length', stat.st_size)
        self.send_header('Last-Modified', last_modified)
        self.end_headers()

        if self.method != 'HEAD':
            self._response = file(path, 'rb')
            file_wrapper = self.environ.get('wsgi.file_wrapper')
            if file_wrapper:
                self._response = file_wrapper(self._response, 4096)
        raise RequestDone
Example #12
0
def render_zip(req, filename, repos, root_node, iter_nodes):
    """Send a ZIP file containing the data corresponding to the `nodes`
    iterable.

    :type root_node: `~trac.versioncontrol.api.Node`
    :param root_node: optional ancestor for all the *nodes*

    :param iter_nodes: callable taking the optional *root_node* as input
                       and generating the `~trac.versioncontrol.api.Node`
                       for which the content should be added into the zip.
    """
    req.send_response(200)
    req.send_header('Content-Type', 'application/zip')
    req.send_header('Content-Disposition',
                    content_disposition('inline', filename))
    if root_node:
        req.send_header('Last-Modified', http_date(root_node.last_modified))
        root_path = root_node.path.rstrip('/')
    else:
        root_path = ''
    if root_path:
        root_path += '/'
        root_name = root_node.name + '/'
    else:
        root_name = ''
    root_len = len(root_path)

    buf = StringIO()
    zipfile = ZipFile(buf, 'w', ZIP_DEFLATED)
    for node in iter_nodes(root_node):
        if node is root_node:
            continue
        path = node.path.strip('/')
        assert path.startswith(root_path)
        path = root_name + path[root_len:]
        kwargs = {'mtime': node.last_modified}
        data = None
        if node.isfile:
            data = node.get_processed_content(eol_hint='CRLF').read()
            properties = node.get_properties()
            # Subversion specific
            if 'svn:special' in properties and data.startswith('link '):
                data = data[5:]
                kwargs['symlink'] = True
            if 'svn:executable' in properties:
                kwargs['executable'] = True
        elif node.isdir and path:
            kwargs['dir'] = True
            data = ''
        if data is not None:
            zipfile.writestr(create_zipinfo(path, **kwargs), data)
    zipfile.close()

    zip_str = buf.getvalue()
    req.send_header("Content-Length", len(zip_str))
    req.end_headers()
    req.write(zip_str)
    raise RequestDone
Example #13
0
def render_zip(req, filename, repos, root_node, iter_nodes):
    """Send a ZIP file containing the data corresponding to the `nodes`
    iterable.

    :type root_node: `~trac.versioncontrol.api.Node`
    :param root_node: optional ancestor for all the *nodes*

    :param iter_nodes: callable taking the optional *root_node* as input
                       and generating the `~trac.versioncontrol.api.Node`
                       for which the content should be added into the zip.
    """
    req.send_response(200)
    req.send_header('Content-Type', 'application/zip')
    req.send_header('Content-Disposition',
                    content_disposition('inline', filename))
    if root_node:
        req.send_header('Last-Modified', http_date(root_node.last_modified))
        root_path = root_node.path.rstrip('/')
    else:
        root_path = ''
    if root_path:
        root_path += '/'
        root_name = root_node.name + '/'
    else:
        root_name = ''
    root_len = len(root_path)

    buf = StringIO()
    zipfile = ZipFile(buf, 'w', ZIP_DEFLATED)
    for node in iter_nodes(root_node):
        if node is root_node:
            continue
        path = node.path.strip('/')
        assert path.startswith(root_path)
        path = root_name + path[root_len:]
        kwargs = {'mtime': node.last_modified}
        data = None
        if node.isfile:
            data = node.get_processed_content(eol_hint='CRLF').read()
            properties = node.get_properties()
            # Subversion specific
            if 'svn:special' in properties and data.startswith('link '):
                data = data[5:]
                kwargs['symlink'] = True
            if 'svn:executable' in properties:
                kwargs['executable'] = True
        elif node.isdir and path:
            kwargs['dir'] = True
            data = ''
        if data is not None:
            zipfile.writestr(create_zipinfo(path, **kwargs), data)
    zipfile.close()

    zip_str = buf.getvalue()
    req.send_header("Content-Length", len(zip_str))
    req.end_headers()
    req.write(zip_str)
    raise RequestDone
Example #14
0
def populate_hdf(hdf, env, req=None):
    """Populate the HDF data set with various information, such as common URLs,
    project information and request-related information.
    FIXME: do we really have req==None at times?
    """
    from trac import __version__
    hdf['trac'] = {
        'version': __version__,
        'time': format_datetime(),
        'time.gmt': http_date()
    }
    hdf['project'] = {
        'shortname': os.path.basename(env.path),
        'name': env.project_name,
        'name_encoded': env.project_name,
        'descr': env.project_description,
        'footer': Markup(env.project_footer),
        'url': env.project_url
    }

    if req:
        hdf['trac.href'] = {
            'wiki': req.href.wiki(),
            'browser': req.href.browser('/'),
            'timeline': req.href.timeline(),
            'roadmap': req.href.roadmap(),
            'milestone': req.href.milestone(None),
            'report': req.href.report(),
            'query': req.href.query(),
            'newticket': req.href.newticket(),
            'search': req.href.search(),
            'about': req.href.about(),
            'about_config': req.href.about('config'),
            'login': req.href.login(),
            'logout': req.href.logout(),
            'settings': req.href.settings(),
            'homepage': 'http://trac.edgewall.org/'
        }

        hdf['base_url'] = req.base_url
        hdf['base_host'] = req.base_url[:req.base_url.rfind(req.base_path)]
        hdf['cgi_location'] = req.base_path
        hdf['trac.authname'] = req.authname

        if req.perm:
            for action in req.perm.permissions():
                req.hdf['trac.acl.' + action] = True

        for arg in [k for k in req.args.keys() if k]:
            if isinstance(req.args[arg], (list, tuple)):
                hdf['args.%s' % arg] = [v for v in req.args[arg]]
            elif isinstance(req.args[arg], basestring):
                hdf['args.%s' % arg] = req.args[arg]
Example #15
0
def populate_hdf(hdf, env, req=None):
    """Populate the HDF data set with various information, such as common URLs,
    project information and request-related information.
    FIXME: do we really have req==None at times?
    """
    from trac import __version__
    hdf['trac'] = {
        'version': __version__,
        'time': format_datetime(),
        'time.gmt': http_date()
    }
    hdf['project'] = {
        'shortname': os.path.basename(env.path),
        'name': env.project_name,
        'name_encoded': env.project_name,
        'descr': env.project_description,
        'footer': Markup(env.project_footer),
        'url': env.project_url
    }

    if req:
        hdf['trac.href'] = {
            'wiki': req.href.wiki(),
            'browser': req.href.browser('/'),
            'timeline': req.href.timeline(),
            'roadmap': req.href.roadmap(),
            'milestone': req.href.milestone(None),
            'report': req.href.report(),
            'query': req.href.query(),
            'newticket': req.href.newticket(),
            'search': req.href.search(),
            'about': req.href.about(),
            'about_config': req.href.about('config'),
            'login': req.href.login(),
            'logout': req.href.logout(),
            'settings': req.href.settings(),
            'homepage': 'http://trac.edgewall.org/'
        }

        hdf['base_url'] = req.base_url
        hdf['base_host'] = req.base_url[:req.base_url.rfind(req.base_path)]
        hdf['cgi_location'] = req.base_path
        hdf['trac.authname'] = req.authname

        if req.perm:
            for action in req.perm.permissions():
                req.hdf['trac.acl.' + action] = True

        for arg in [k for k in req.args.keys() if k]:
            if isinstance(req.args[arg], (list, tuple)):
                hdf['args.%s' % arg] = [v for v in req.args[arg]]
            elif isinstance(req.args[arg], basestring):
                hdf['args.%s' % arg] = req.args[arg]
Example #16
0
    def send_file(self, path, mimetype=None, expires=None):
        """Send a local file to the browser.
        
        This method includes the "Last-Modified", "Content-Type" and
        "Content-Length" headers in the response, corresponding to the file
        attributes. It also checks the last modification time of the local file
        against the "If-Modified-Since" provided by the user agent, and sends a
        "304 Not Modified" response if it matches.
        """
        if not os.path.isfile(path):
            raise HTTPNotFound(_("File %(path)s not found", path=path))

        stat = os.stat(path)
        mtime = datetime.fromtimestamp(stat.st_mtime, localtz)
        last_modified = http_date(mtime)
        if last_modified == self.get_header('If-Modified-Since'):
            self.send_response(304)
            self.send_header('Content-Length', 0)
            self.end_headers()
            raise RequestDone

        if not mimetype:
            mimetype = mimetypes.guess_type(path)[0] or \
                       'application/octet-stream'

        self.send_response(200)
        self.send_header('Content-Type', mimetype)
        self.send_header('Content-Length', stat.st_size)
        self.send_header('Last-Modified', last_modified)
        if expires is not None:
            self.send_header('Expires', http_date(expires))
        self.end_headers()

        if self.method != 'HEAD':
            fileobj = file(path, 'rb')
            file_wrapper = self.environ.get('wsgi.file_wrapper', _FileWrapper)
            self._response = file_wrapper(fileobj, 4096)
        raise RequestDone
Example #17
0
    def send_file(self, req, download_id):
        import os
        from datetime import datetime
        from trac.util.datefmt import http_date, localtz
        from trac.web.api import RequestDone
        from trac.web.wsgi import _FileWrapper
        import mimetypes

        Session = session(self.env)
        download = Session.query(Download).get(download_id)

        stat = os.stat(download.path)
        mtime = datetime.fromtimestamp(stat.st_mtime, localtz)
        last_modified = http_date(mtime)
        if last_modified == req.get_header('If-Modified-Since'):
            req.send_response(304)
            req.end_headers()
            raise RequestDone

        mimetype = mimetypes.guess_type(download.path)[0] or 'application/octet-stream'

        req.send_response(200)
        req.send_header('Content-Type', mimetype)
        req.send_header('Content-Length', stat.st_size)
        req.send_header('Last-Modified', last_modified)
        req.end_headers()

        if req.method != 'HEAD':
            fileobj = file(download.path, 'rb')
            file_wrapper = req.environ.get('wsgi.file_wrapper', _FileWrapper)
            buffer = fileobj.read(4096)
            try:
                while buffer:
                    print 'inside loop'
                    try:
                        req._write(buffer)
                        buffer = fileobj.read(4096)
                    except EOFError:
                        raise RequestDone
            except Exception, err:
                raise err
            else:
                download.stats.append(Stat(req.authname))
                Session.commit()
                print 'fooo'
            print '\n\n\n\nAfter'
Example #18
0
    def process_request(self, req):
        # settings panel
        if not 'style' in req.args:
            req._no_pygments_stylesheet = True
            styles = list(get_all_styles())
            styles.sort(lambda a, b: cmp(a.lower(), b.lower()))

            if req.method == 'POST':
                style = req.args.get('new_style')
                if style and style in styles:
                    req.session['pygments_style'] = style

            output = self._highlight('html', self.EXAMPLE, False)
            req.hdf['output'] = Markup(output)
            req.hdf['current'] = req.session.get('pygments_style',
                                                 self.default_style)
            req.hdf['styles'] = styles
            req.hdf['pygments_path'] = self.env.href.pygments()
            return 'pygments_settings.cs', None

        # provide stylesheet
        else:
            style = req.args['style']

            parts = style.__module__.split('.')
            filename = resource_filename('.'.join(parts[:-1]),
                                         parts[-1] + '.py')
            mtime = datetime.utcfromtimestamp(os.path.getmtime(filename))
            last_modified = http_date(time.mktime(mtime.timetuple()))
            if last_modified == req.get_header('If-Modified-Since'):
                req.send_response(304)
                req.end_headers()
                return

            formatter = HtmlFormatter(style=style)
            content = u'\n\n'.join([
                formatter.get_style_defs('div.code pre'),
                formatter.get_style_defs('table.code td')
            ]).encode('utf-8')

            req.send_response(200)
            req.send_header('Content-Type', 'text/css; charset=utf-8')
            req.send_header('Last-Modified', last_modified)
            req.send_header('Content-Length', len(content))
            req.write(content)
Example #19
0
    def process_request(self, req):
        # settings panel
        if not 'style' in req.args:
            req._no_pygments_stylesheet = True
            styles = list(get_all_styles())
            styles.sort(lambda a, b: cmp(a.lower(), b.lower()))

            if req.method == 'POST':
                style = req.args.get('new_style')
                if style and style in styles:
                    req.session['pygments_style'] = style

            output = self._highlight('html', self.EXAMPLE, False)
            req.hdf['output'] = Markup(output)
            req.hdf['current'] = req.session.get('pygments_style',
                                                 self.default_style)
            req.hdf['styles'] = styles
            req.hdf['pygments_path'] = self.env.href.pygments()
            return 'pygments_settings.cs', None

        # provide stylesheet
        else:
            style = req.args['style']

            parts = style.__module__.split('.')
            filename = resource_filename('.'.join(parts[:-1]), parts[-1] + '.py')
            mtime = datetime.utcfromtimestamp(os.path.getmtime(filename))
            last_modified = http_date(time.mktime(mtime.timetuple()))
            if last_modified == req.get_header('If-Modified-Since'):
                req.send_response(304)
                req.end_headers()
                return

            formatter = HtmlFormatter(style=style)
            content = u'\n\n'.join([
                formatter.get_style_defs('div.code pre'),
                formatter.get_style_defs('table.code td')
            ]).encode('utf-8')

            req.send_response(200)
            req.send_header('Content-Type', 'text/css; charset=utf-8')
            req.send_header('Last-Modified', last_modified)
            req.send_header('Content-Length', len(content))
            req.write(content)
Example #20
0
    def send_file(self, path, mimetype=None):
        """Send a local file to the browser.

        This method includes the "Last-Modified", "Content-Type" and
        "Content-Length" headers in the response, corresponding to the file
        attributes. It also checks the last modification time of the local file
        against the "If-Modified-Since" provided by the user agent, and sends a
        "304 Not Modified" response if it matches.
        """
        if not os.path.isfile(path):
            raise HTTPNotFound(_("File %(path)s not found", path=path))

        stat = os.stat(path)
        mtime = datetime.fromtimestamp(stat.st_mtime, localtz)
        last_modified = http_date(mtime)
        if last_modified == self.get_header('If-Modified-Since'):
            self.send_response(304)
            self.send_header('Content-Length', 0)
            self.end_headers()
            raise RequestDone

        if not mimetype:
            mimetype = mimetypes.guess_type(path)[0] or \
                       'application/octet-stream'

        self.send_response(200)
        self.send_header('Content-Type', mimetype)
        self.send_header('Content-Length', stat.st_size)
        self.send_header('Last-Modified', last_modified)
        use_xsendfile = getattr(self, 'use_xsendfile', False)
        if use_xsendfile:
            xsendfile_header = getattr(self, 'xsendfile_header', None)
            if xsendfile_header:
                self.send_header(xsendfile_header, os.path.abspath(path))
            else:
                use_xsendfile = False
        self.end_headers()

        if not use_xsendfile and self.method != 'HEAD':
            fileobj = open(path, 'rb')
            file_wrapper = self.environ.get('wsgi.file_wrapper', _FileWrapper)
            self._response = file_wrapper(fileobj, 4096)
        raise RequestDone
Example #21
0
    def runTest(self):
        """Test timeline in RSS format."""
        pagename = random_unique_camel()
        self._tester.create_wiki_page(pagename)
        page = WikiPage(self._testenv.get_trac_environment(), pagename)
        self._tester.go_to_timeline()
        code, content = tc.download_link("RSS Feed")
        self.assertEqual(200, code)
        pattern = r"""<\?xml version="1.0"\?>[\n]+
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Functional Tests</title>
    <link>http://127.0.0.1:\d+/timeline</link>
    <description>Trac Timeline</description>
    <language>en-US</language>
    <generator>Trac [^<]+</generator>
    <image>
      <title>Functional Tests</title>
      <url>http://127.0.0.1:\d+/chrome/site/your_project_logo.png</url>
      <link>http://127.0.0.1:\d+/timeline</link>
    </image>
    <item>
      <title>%(pagename)s created</title>

      <dc:creator>admin</dc:creator>
      <pubDate>%(http_date)s</pubDate>
      <link>http://127.0.0.1:\d+/wiki/%(pagename)s\?version=1</link>
      <guid isPermaLink="false">http://127.0.0.1:\d+/wiki/%(pagename)s\?version=1/\d+</guid>
      <description>[^<]+</description>
      <category>wiki</category>
    </item>
""" % {
            'pagename': pagename,
            'http_date': http_date(page.time)
        }
        if not re.match(pattern.encode('utf-8'), content,
                        re.MULTILINE | re.DOTALL):
            url = tc.write_source(content)
            raise AssertionError(
                "Regex didn't match: {!r} not found in {}".format(
                    pattern, url))
Example #22
0
 def export_rss(self, req, query):
     query.verbose = True
     db = self.env.get_db_cnx()
     results = query.execute(req, db)
     for result in results:
         result['href'] = req.abs_href.ticket(result['id'])
         if result['reporter'].find('@') == -1:
             result['reporter'] = ''
         if result['description']:
             # unicode() cancels out the Markup() returned by wiki_to_html
             descr = wiki_to_html(result['description'], self.env, req, db,
                                  absurls=True)
             result['description'] = unicode(descr)
         if result['time']:
             result['time'] = http_date(result['time'])
     req.hdf['query.results'] = results
     req.hdf['query.href'] = req.abs_href.query(group=query.group,
             groupdesc=query.groupdesc and 1 or None,
             verbose=query.verbose and 1 or None,
             **query.constraints)
     return (req.hdf.render('query_rss.cs'), 'application/rss+xml')
Example #23
0
 def grouped_changelog_entries(self, ticket, db, when=0):
     """Iterate on changelog entries, consolidating related changes
     in a `dict` object.
     """
     changelog = ticket.get_changelog(when=when, db=db)
     autonum = 0 # used for "root" numbers
     last_uid = current = None
     for date, author, field, old, new, permanent in changelog:
         uid = date, author, permanent
         if uid != last_uid:
             if current:
                 yield current
             last_uid = uid
             current = {
                 'http_date': http_date(date),
                 'date': format_datetime(date),
                 'author': author,
                 'fields': {},
                 'permanent': permanent
             }
             if permanent and not when:
                 autonum += 1
                 current['cnum'] = autonum
         # some common processing for fields
         if field == 'comment':
             current['comment'] = new
             if old:
                 if '.' in old: # retrieve parent.child relationship
                     parent_num, this_num = old.split('.', 1)
                     current['replyto'] = parent_num
                 else:
                     this_num = old
                 current['cnum'] = int(this_num)
         else:
             current['fields'][field] = {'old': old, 'new': new}
     if current:
         yield current
Example #24
0
 def grouped_changelog_entries(self, ticket, db, when=0):
     """Iterate on changelog entries, consolidating related changes
     in a `dict` object.
     """
     changelog = ticket.get_changelog(when=when, db=db)
     autonum = 0  # used for "root" numbers
     last_uid = current = None
     for date, author, field, old, new, permanent in changelog:
         uid = date, author, permanent
         if uid != last_uid:
             if current:
                 yield current
             last_uid = uid
             current = {
                 'http_date': http_date(date),
                 'date': format_datetime(date),
                 'author': author,
                 'fields': {},
                 'permanent': permanent
             }
             if permanent and not when:
                 autonum += 1
                 current['cnum'] = autonum
         # some common processing for fields
         if field == 'comment':
             current['comment'] = new
             if old:
                 if '.' in old:  # retrieve parent.child relationship
                     parent_num, this_num = old.split('.', 1)
                     current['replyto'] = parent_num
                 else:
                     this_num = old
                 current['cnum'] = int(this_num)
         else:
             current['fields'][field] = {'old': old, 'new': new}
     if current:
         yield current
Example #25
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 #26
0
    def process_request(self, req):
        req.perm.assert_permission('LOG_VIEW')

        mode = req.args.get('mode', 'stop_on_copy')
        path = req.args.get('path', '/')
        rev = req.args.get('rev')
        stop_rev = req.args.get('stop_rev')
        format = req.args.get('format')
        verbose = req.args.get('verbose')
        limit = LOG_LIMIT

        repos = self.env.get_repository(req.authname)
        normpath = repos.normalize_path(path)
        rev = unicode(repos.normalize_rev(rev))
        if stop_rev:
            stop_rev = unicode(repos.normalize_rev(stop_rev))
            if repos.rev_older_than(rev, stop_rev):
                rev, stop_rev = stop_rev, rev

        req.hdf['title'] = path + ' (log)'
        req.hdf['log'] = {
            'mode': mode,
            'path': path,
            'rev': rev,
            'verbose': verbose,
            'stop_rev': stop_rev,
            'browser_href': req.href.browser(path),
            'changeset_href': req.href.changeset(),
            'log_href': req.href.log(path, rev=rev)
        }

        path_links = get_path_links(req.href, path, rev)
        req.hdf['log.path'] = path_links
        if path_links:
            add_link(req, 'up', path_links[-1]['href'], u'Répertoire parent')

        # The `history()` method depends on the mode:
        #  * for ''stop on copy'' and ''follow copies'', it's `Node.history()`
        #  * for ''show only add, delete'' it's`Repository.get_path_history()`
        if mode == 'path_history':

            def history(limit):
                for h in repos.get_path_history(path, rev, limit):
                    yield h
        else:
            history = get_existing_node(req, repos, path, rev).get_history

        # -- retrieve history, asking for limit+1 results
        info = []
        previous_path = repos.normalize_path(path)
        for old_path, old_rev, old_chg in history(limit + 1):
            if stop_rev and repos.rev_older_than(old_rev, stop_rev):
                break
            old_path = repos.normalize_path(old_path)
            item = {
                'rev': str(old_rev),
                'path': old_path,
                'log_href': req.href.log(old_path, rev=old_rev),
                'browser_href': req.href.browser(old_path, rev=old_rev),
                'changeset_href': req.href.changeset(old_rev),
                'restricted_href': req.href.changeset(old_rev,
                                                      new_path=old_path),
                'change': old_chg
            }
            if not (mode == 'path_history' and old_chg == Changeset.EDIT):
                info.append(item)
            if old_path and old_path != previous_path \
               and not (mode == 'path_history' and old_path == normpath):
                item['copyfrom_path'] = old_path
                if mode == 'stop_on_copy':
                    break
            if len(info) > limit:  # we want limit+1 entries
                break
            previous_path = old_path
        if info == []:
            # FIXME: we should send a 404 error here
            raise TracError(
                u"Le fichier ou le répertoire '%s' n'existe pas "
                u"en révision %s ou pour toute révision précédente." %
                (path, rev), u'Chemin inexistant')

        def make_log_href(path, **args):
            link_rev = rev
            if rev == str(repos.youngest_rev):
                link_rev = None
            params = {'rev': link_rev, 'mode': mode, 'limit': limit}
            params.update(args)
            if verbose:
                params['verbose'] = verbose
            return req.href.log(path, **params)

        if len(info
               ) == limit + 1:  # limit+1 reached, there _might_ be some more
            next_rev = info[-1]['rev']
            next_path = info[-1]['path']
            add_link(
                req, 'next', make_log_href(next_path, rev=next_rev),
                u'Journal des révisions (repartant de %s, rév. %s)' %
                (next_path, next_rev))
            # now, only show 'limit' results
            del info[-1]

        req.hdf['log.items'] = info

        revs = [i['rev'] for i in info]
        changes = get_changes(self.env, repos, revs, verbose, req, format)
        if format == 'rss':
            # Get the email addresses of all known users
            email_map = {}
            for username, name, email in self.env.get_known_users():
                if email:
                    email_map[username] = email
            for cs in changes.values():
                # For RSS, author must be an email address
                author = cs['author']
                author_email = ''
                if '@' in author:
                    author_email = author
                elif email_map.has_key(author):
                    author_email = email_map[author]
                cs['author'] = author_email
                cs['date'] = http_date(cs['date_seconds'])
        elif format == 'changelog':
            for rev in revs:
                changeset = repos.get_changeset(rev)
                cs = changes[rev]
                cs['message'] = wrap(changeset.message,
                                     70,
                                     initial_indent='\t',
                                     subsequent_indent='\t')
                files = []
                actions = []
                for path, kind, chg, bpath, brev in changeset.get_changes():
                    files.append(chg == Changeset.DELETE and bpath or path)
                    actions.append(chg)
                cs['files'] = files
                cs['actions'] = actions
        req.hdf['log.changes'] = changes

        if req.args.get('format') == 'changelog':
            return 'log_changelog.cs', 'text/plain'
        elif req.args.get('format') == 'rss':
            return 'log_rss.cs', 'application/rss+xml'

        add_stylesheet(req, 'common/css/browser.css')
        add_stylesheet(req, 'common/css/diff.css')

        rss_href = make_log_href(path, format='rss', stop_rev=stop_rev)
        add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml',
                 'rss')
        changelog_href = make_log_href(path,
                                       format='changelog',
                                       stop_rev=stop_rev)
        add_link(req, 'alternate', changelog_href, 'ChangeLog', 'text/plain')

        return 'log.cs', None
Example #27
0
    def _render_file(self, req, context, repos, node, rev=None):
        req.perm(node.resource).require("FILE_VIEW")

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_processed_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", "text/plain" if format == "txt" else mime_type)
            req.send_header("Last-Modified", http_date(node.last_modified))
            if rev is None:
                req.send_header("Pragma", "no-cache")
                req.send_header("Cache-Control", "no-cache")
                req.send_header("Expires", "Fri, 01 Jan 1999 00:00:00 GMT")
            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()
            # Note: don't pass an iterable instance to RequestDone, instead
            # call req.write() with each chunk here to avoid SEGVs (#11805)
            while chunk:
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
            raise RequestDone
        else:
            # The changeset corresponding to the last change on `node`
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.created_rev)

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != "text/plain":
                plain_href = req.href.browser(repos.reponame or None, 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.export(rev or repos.youngest_rev, repos.reponame or None, node.path)
            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, rev, mime_type)

            content = None  # the remainder of that content is not needed

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

            annotations = ["lineno"]
            annotate = req.args.get("annotate")
            if annotate:
                annotations.insert(0, annotate)
            preview_data = mimeview.preview_data(
                context,
                node.get_processed_content(),
                node.get_content_length(),
                mime_type,
                node.created_path,
                raw_href,
                annotations=annotations,
                force_source=bool(annotate),
            )
            return {"changeset": changeset, "size": node.content_length, "preview": preview_data, "annotate": annotate}
Example #28
0
class TimelineModule(Component):

    implements(INavigationContributor, IPermissionRequestor, IRequestHandler)

    event_providers = ExtensionPoint(ITimelineEventProvider)

    default_daysback = IntOption(
        'timeline', 'default_daysback', 30,
        """Default number of days displayed in the Timeline, in days.
        (''since 0.9.'')""")

    # INavigationContributor methods

    def get_active_navigation_item(self, req):
        return 'timeline'

    def get_navigation_items(self, req):
        if not req.perm.has_permission('TIMELINE_VIEW'):
            return
        yield ('mainnav', 'timeline',
               html.A('Timeline', href=req.href.timeline(), accesskey=2))

    # IPermissionRequestor methods

    def get_permission_actions(self):
        return ['TIMELINE_VIEW']

    # IRequestHandler methods

    def match_request(self, req):
        return re.match(r'/timeline/?', req.path_info) is not None

    def process_request(self, req):
        req.perm.assert_permission('TIMELINE_VIEW')

        format = req.args.get('format')
        maxrows = int(req.args.get('max', 0))

        # Parse the from date and adjust the timestamp to the last second of
        # the day
        t = time.localtime()
        if req.args.has_key('from'):
            try:
                t = time.strptime(req.args.get('from'), '%x')
            except:
                pass

        fromdate = time.mktime(
            (t[0], t[1], t[2], 23, 59, 59, t[6], t[7], t[8]))
        try:
            daysback = max(0, int(req.args.get('daysback', '')))
        except ValueError:
            daysback = self.default_daysback
        req.hdf['timeline.from'] = format_date(fromdate)
        req.hdf['timeline.daysback'] = daysback

        available_filters = []
        for event_provider in self.event_providers:
            available_filters += event_provider.get_timeline_filters(req)

        filters = []
        # check the request or session for enabled filters, or use default
        for test in (lambda f: req.args.has_key(f[0]),
                     lambda f: req.session.get('timeline.filter.%s' % f[0], '')\
                               == '1',
                     lambda f: len(f) == 2 or f[2]):
            if filters:
                break
            filters = [f[0] for f in available_filters if test(f)]

        # save the results of submitting the timeline form to the session
        if req.args.has_key('update'):
            for filter in available_filters:
                key = 'timeline.filter.%s' % filter[0]
                if req.args.has_key(filter[0]):
                    req.session[key] = '1'
                elif req.session.has_key(key):
                    del req.session[key]

        stop = fromdate
        start = stop - (daysback + 1) * 86400

        events = []
        for event_provider in self.event_providers:
            try:
                events += event_provider.get_timeline_events(
                    req, start, stop, filters)
            except Exception, e:  # cope with a failure of that provider
                self._provider_failure(e, req, event_provider, filters,
                                       [f[0] for f in available_filters])

        events.sort(lambda x, y: cmp(y[3], x[3]))
        if maxrows and len(events) > maxrows:
            del events[maxrows:]

        req.hdf['title'] = 'Timeline'

        # Get the email addresses of all known users
        email_map = {}
        for username, name, email in self.env.get_known_users():
            if email:
                email_map[username] = email

        idx = 0
        for kind, href, title, date, author, message in events:
            event = {
                'kind': kind,
                'title': title,
                'href': href,
                'author': author or 'anonymous',
                'date': format_date(date),
                'time': format_time(date, '%H:%M'),
                'dateuid': int(date),
                'message': message
            }

            if format == 'rss':
                # Strip/escape HTML markup
                if isinstance(title, Markup):
                    title = title.plaintext(keeplinebreaks=False)
                event['title'] = title
                event['message'] = to_unicode(message)

                if author:
                    # For RSS, author must be an email address
                    event['author.email'] = '*****@*****.**'
#                    if author.find('@') != -1:
#                        event['author.email'] = author
#                    elif email_map.has_key(author):
#                        event['author.email'] = email_map[author]
                event['date'] = http_date(date)

            req.hdf['timeline.events.%s' % idx] = event
            idx += 1

        if format == 'rss':
            return 'timeline_rss.cs', 'application/rss+xml'

        add_stylesheet(req, 'common/css/timeline.css')
        rss_href = req.href.timeline([(f, 'on') for f in filters],
                                     daysback=90,
                                     max=50,
                                     format='rss')
        add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml',
                 'rss')
        for idx, fltr in enumerate(available_filters):
            req.hdf['timeline.filters.%d' % idx] = {
                'name': fltr[0],
                'label': fltr[1],
                'enabled': int(fltr[0] in filters)
            }

        return 'timeline.cs', None
Example #29
0
File: log.py Project: yeoupooh/tow
    def process_request(self, req):
        req.perm.assert_permission('LOG_VIEW')

        mode = req.args.get('mode', 'stop_on_copy')
        path = req.args.get('path', '/')
        rev = req.args.get('rev')
        stop_rev = req.args.get('stop_rev')
        format = req.args.get('format')
        verbose = req.args.get('verbose')
        limit = LOG_LIMIT

        repos = self.env.get_repository(req.authname)
        normpath = repos.normalize_path(path)
        rev = unicode(repos.normalize_rev(rev))
        if stop_rev:
            stop_rev = unicode(repos.normalize_rev(stop_rev))
            if repos.rev_older_than(rev, stop_rev):
                rev, stop_rev = stop_rev, rev
            
        req.hdf['title'] = path + ' (log)'
        req.hdf['log'] = {
            'mode': mode,
            'path': path,
            'rev': rev,
            'verbose': verbose,
            'stop_rev': stop_rev,
            'browser_href': req.href.browser(path),
            'changeset_href': req.href.changeset(),
            'log_href': req.href.log(path, rev=rev)
        }

        path_links = get_path_links(req.href, path, rev)
        req.hdf['log.path'] = path_links
        if path_links:
            add_link(req, 'up', path_links[-1]['href'], 'Parent directory')

        # The `history()` method depends on the mode:
        #  * for ''stop on copy'' and ''follow copies'', it's `Node.history()` 
        #  * for ''show only add, delete'' it's`Repository.get_path_history()` 
        if mode == 'path_history':
            def history(limit):
                for h in repos.get_path_history(path, rev, limit):
                    yield h
        else:
            history = get_existing_node(req, repos, path, rev).get_history

        # -- retrieve history, asking for limit+1 results
        info = []
        previous_path = repos.normalize_path(path)
        for old_path, old_rev, old_chg in history(limit+1):
            if stop_rev and repos.rev_older_than(old_rev, stop_rev):
                break
            old_path = repos.normalize_path(old_path)
            item = {
                'rev': str(old_rev),
                'path': old_path,
                'log_href': req.href.log(old_path, rev=old_rev),
                'browser_href': req.href.browser(old_path, rev=old_rev),
                'changeset_href': req.href.changeset(old_rev),
                'restricted_href': req.href.changeset(old_rev, new_path=old_path),
                'change': old_chg
            }
            if not (mode == 'path_history' and old_chg == Changeset.EDIT):
                info.append(item)
            if old_path and old_path != previous_path \
               and not (mode == 'path_history' and old_path == normpath):
                item['copyfrom_path'] = old_path
                if mode == 'stop_on_copy':
                    break
            if len(info) > limit: # we want limit+1 entries
                break
            previous_path = old_path
        if info == []:
            # FIXME: we should send a 404 error here
            raise TracError("The file or directory '%s' doesn't exist "
                            "at revision %s or at any previous revision."
                            % (path, rev), 'Nonexistent path')

        def make_log_href(path, **args):
            link_rev = rev
            if rev == str(repos.youngest_rev):
                link_rev = None
            params = {'rev': link_rev, 'mode': mode, 'limit': limit}
            params.update(args)
            if verbose:
                params['verbose'] = verbose
            return req.href.log(path, **params)

        if len(info) == limit+1: # limit+1 reached, there _might_ be some more
            next_rev = info[-1]['rev']
            next_path = info[-1]['path']
            add_link(req, 'next', make_log_href(next_path, rev=next_rev),
                     u'리비전 로그 ( %s, 리비전 %s 에서 다시 시작)'
                     % (next_path, next_rev))
            # now, only show 'limit' results
            del info[-1]
        
        req.hdf['log.items'] = info

        revs = [i['rev'] for i in info]
        changes = get_changes(self.env, repos, revs, verbose, req, format)
        if format == 'rss':
            # Get the email addresses of all known users
            email_map = {}
            for username,name,email in self.env.get_known_users():
                if email:
                    email_map[username] = email
            for cs in changes.values():
                # For RSS, author must be an email address
                author = cs['author']
                author_email = ''
                if '@' in author:
                    author_email = author
                elif email_map.has_key(author):
                    author_email = email_map[author]
                cs['author'] = author_email
                cs['date'] = http_date(cs['date_seconds'])
        elif format == 'changelog':
            for rev in revs:
                changeset = repos.get_changeset(rev)
                cs = changes[rev]
                cs['message'] = wrap(changeset.message, 70,
                                     initial_indent='\t',
                                     subsequent_indent='\t')
                files = []
                actions = []
                for path, kind, chg, bpath, brev in changeset.get_changes():
                    files.append(chg == Changeset.DELETE and bpath or path)
                    actions.append(chg)
                cs['files'] = files
                cs['actions'] = actions
        req.hdf['log.changes'] = changes

        if req.args.get('format') == 'changelog':
            return 'log_changelog.cs', 'text/plain'
        elif req.args.get('format') == 'rss':
            return 'log_rss.cs', 'application/rss+xml'

        add_stylesheet(req, 'common/css/browser.css')
        add_stylesheet(req, 'common/css/diff.css')

        rss_href = make_log_href(path, format='rss', stop_rev=stop_rev)
        add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml',
                 'rss')
        changelog_href = make_log_href(path, format='changelog',
                                       stop_rev=stop_rev)
        add_link(req, 'alternate', changelog_href, 'ChangeLog', 'text/plain')

        return 'log.cs', None
Example #30
0
class SimileTimelineModule(Component):

    implements(ITemplateProvider, IRequestHandler, INavigationContributor)

    # IRequestHandler methods
    def match_request(self, req):
        return req.path_info.startswith('/stimeline')

    def process_request(self, req):
        req.perm.assert_permission('TIMELINE_VIEW')

        format = req.args.get('format')
        maxrows = int(req.args.get('max', 0))

        # Parse the from date and adjust the timestamp to the last second of
        # the day
        t = time.localtime()
        if req.args.has_key('from'):
            try:
                t = time.strptime(req.args.get('from'), '%x')
            except:
                pass

        fromdate = time.mktime(
            (t[0], t[1], t[2], 23, 59, 59, t[6], t[7], t[8]))
        try:
            daysback = max(0, int(req.args.get('daysback', '')))
        except ValueError:
            daysback = TimelineModule(self.env).default_daysback
        req.hdf['timeline.from'] = format_date(fromdate)
        req.hdf['timeline.daysback'] = daysback

        available_filters = []
        for event_provider in TimelineModule(self.env).event_providers:
            available_filters += event_provider.get_timeline_filters(req)

        filters = []
        # check the request or session for enabled filters, or use default
        for test in (lambda f: req.args.has_key(f[0]),
                     lambda f: req.session.get('timeline.filter.%s' % f[0], '')\
                               == '1',
                     lambda f: len(f) == 2 or f[2]):
            if filters:
                break
            filters = [f[0] for f in available_filters if test(f)]

        # save the results of submitting the timeline form to the session
        if req.args.has_key('update'):
            for filter in available_filters:
                key = 'timeline.filter.%s' % filter[0]
                if req.args.has_key(filter[0]):
                    req.session[key] = '1'
                elif req.session.has_key(key):
                    del req.session[key]

        stop = fromdate
        start = stop - (daysback + 1) * 86400

        events = []
        for event_provider in TimelineModule(self.env).event_providers:
            try:
                events += event_provider.get_timeline_events(
                    req, start, stop, filters)
            except Exception, e:  # cope with a failure of that provider
                self._provider_failure(e, req, event_provider, filters,
                                       [f[0] for f in available_filters])

        events.sort(lambda x, y: cmp(y[3], x[3]))
        if maxrows and len(events) > maxrows:
            del events[maxrows:]

        req.hdf['title'] = 'Timeline'

        # Get the email addresses of all known users
        email_map = {}
        for username, name, email in self.env.get_known_users():
            if email:
                email_map[username] = email

        idx = 0
        for kind, href, title, date, author, message in events:
            event = {
                'kind': kind,
                'title': re.sub(r'<[^>]*>', '', unicode(title)),
                'href': href,
                'author': author or 'anonymous',
                'date': format_date(date, '%m/%d/%Y'),
                'time': format_time(date, '%H:%M'),
                'message': message.replace('&hellip;', '...'),
                'icon': req.href.chrome('common', kind + '.png')
            }

            if format == 'rss':
                # Strip/escape HTML markup
                if isinstance(title, Markup):
                    title = title.plaintext(keeplinebreaks=False)
                event['title'] = title
                event['message'] = to_unicode(message)

                if author:
                    # For RSS, author must be an email address
                    if author.find('@') != -1:
                        event['author.email'] = author
                    elif email_map.has_key(author):
                        event['author.email'] = email_map[author]
                event['date'] = http_date(date)

            req.hdf['timeline.events.%s' % idx] = event
            idx += 1

        if format == 'rss':
            return 'timeline_rss.cs', 'application/rss+xml'
        if format == 'xml':
            return 'stimeline_xml.cs', 'application/xml'

        add_stylesheet(req, 'common/css/timeline.css')
        rss_href = req.href.timeline([(f, 'on') for f in filters],
                                     daysback=90,
                                     max=50,
                                     format='rss')
        add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml',
                 'rss')
        for idx, fltr in enumerate(available_filters):
            req.hdf['timeline.filters.%d' % idx] = {
                'name': fltr[0],
                'label': fltr[1],
                'enabled': int(fltr[0] in filters)
            }

        ## NEW LINES
        add_script(req, 'stimeline/js/simile/timeline-api.js')
        #add_abs_script(req, "http://simile.mit.edu/timeline/api/timeline-api.js")
        add_script(req, 'stimeline/js/simile.js')
        xml_args = {
            'daysback': daysback,
            'from': time.strftime('%x', time.localtime(fromdate)),
            'format': 'xml',
        }
        xml_args.update(dict([(f, 'on') for f in filters]))

        xml_href = req.href.stimeline(**xml_args)
        req.hdf['stimeline.xml_href'] = Markup(xml_href)
        req.hdf['stimeline.href'] = req.href.stimeline()

        return 'stimeline.cs', None
Example #31
0
                    if cell.find('@') != -1:
                        value['rss'] = cell
                    elif cell in email_map:
                        value['rss'] = email_map[cell]
                elif column == 'report':
                    value['report_href'] = req.href.report(cell)
                elif column in ('time', 'date', 'changetime', 'created',
                                'modified'):
                    if cell == 'None':
                        value['date'] = value['time'] = cell
                        value['datetime'] = value['gmt'] = cell
                    else:
                        value['date'] = format_date(cell)
                        value['time'] = format_time(cell)
                        value['datetime'] = format_datetime(cell)
                        value['gmt'] = http_date(cell)
                prefix = 'report.items.%d.%s' % (row_idx, unicode(column))
                req.hdf[prefix] = unicode(cell)
                for key in value.keys():
                    req.hdf[prefix + '.' + key] = value[key]

                col_idx += 1
            row_idx += 1
        req.hdf['report.numrows'] = row_idx

        if format == 'rss':
            return 'report_rss.cs', 'application/rss+xml'
        elif format == 'csv':
            self._render_csv(req, cols, rows)
            return None
        elif format == 'tab':
Example #32
0
class PygmentsRenderer(Component):
    """HTML renderer for syntax highlighting based on Pygments."""

    implements(ISystemInfoProvider, IHTMLPreviewRenderer,
               IPreferencePanelProvider, IRequestHandler)

    default_style = Option(
        'mimeviewer', 'pygments_default_style', 'trac',
        """The default style to use for Pygments syntax highlighting.""")

    pygments_modes = ListOption(
        'mimeviewer',
        'pygments_modes',
        '',
        doc="""List of additional MIME types known by Pygments.

        For each, a tuple `mimetype:mode:quality` has to be
        specified, where `mimetype` is the MIME type,
        `mode` is the corresponding Pygments mode to be used
        for the conversion and `quality` is the quality ratio
        associated to this conversion. That can also be used
        to override the default quality ratio used by the
        Pygments render.""")

    expand_tabs = True
    returns_source = True

    QUALITY_RATIO = 7

    EXAMPLE = """<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hello, world!</title>
    <script>
      jQuery(document).ready(function($) {
        $("h1").fadeIn("slow");
      });
    </script>
  </head>
  <body>
    <h1>Hello, world!</h1>
  </body>
</html>"""

    def __init__(self):
        self._types = None

    # ISystemInfoProvider methods

    def get_system_info(self):
        version = get_pkginfo(pygments).get('version')
        # if installed from source, fallback to the hardcoded version info
        if not version and hasattr(pygments, '__version__'):
            version = pygments.__version__
        yield 'Pygments', version

    # IHTMLPreviewRenderer methods

    def get_extra_mimetypes(self):
        for lexname, aliases, _, mimetypes in get_all_lexers():
            for mimetype in mimetypes:
                yield mimetype, aliases

    def get_quality_ratio(self, mimetype):
        # Extend default MIME type to mode mappings with configured ones
        if self._types is None:
            self._init_types()
        try:
            return self._types[mimetype][1]
        except KeyError:
            return 0

    def render(self, context, mimetype, content, filename=None, rev=None):
        req = context.req
        if self._types is None:
            self._init_types()
        add_stylesheet(
            req, '/pygments/%s.css' %
            req.session.get('pygments_style', self.default_style))
        try:
            if len(content) > 0:
                mimetype = mimetype.split(';', 1)[0]
                language = self._types[mimetype][0]
                return self._generate(language, content)
        except (KeyError, ValueError):
            raise Exception("No Pygments lexer found for mime-type '%s'." %
                            mimetype)

    # IPreferencePanelProvider methods

    def get_preference_panels(self, req):
        yield ('pygments', _('Syntax Highlighting'))

    def render_preference_panel(self, req, panel):
        styles = list(get_all_styles())

        if req.method == 'POST':
            style = req.args.get('style')
            if style and style in styles:
                req.session['pygments_style'] = style
                add_notice(req, _('Your preferences have been saved.'))
            req.redirect(req.href.prefs(panel or None))

        output = self._generate('html', self.EXAMPLE)
        return 'prefs_pygments.html', {
            'output': output,
            'selection': req.session.get('pygments_style', self.default_style),
            'styles': styles
        }

    # IRequestHandler methods

    def match_request(self, req):
        match = re.match(r'/pygments/([-\w]+)\.css', req.path_info)
        if match:
            req.args['style'] = match.group(1)
            return True

    def process_request(self, req):
        style = req.args['style']
        try:
            style_cls = get_style_by_name(style)
        except ValueError, e:
            raise HTTPNotFound(e)

        parts = style_cls.__module__.split('.')
        filename = resource_filename('.'.join(parts[:-1]), parts[-1] + '.py')
        mtime = datetime.fromtimestamp(os.path.getmtime(filename), localtz)
        last_modified = http_date(mtime)
        if last_modified == req.get_header('If-Modified-Since'):
            req.send_response(304)
            req.end_headers()
            return

        formatter = HtmlFormatter(style=style_cls)
        content = u'\n\n'.join([
            formatter.get_style_defs('div.code pre'),
            formatter.get_style_defs('table.code td')
        ]).encode('utf-8')

        req.send_response(200)
        req.send_header('Content-Type', 'text/css; charset=utf-8')
        req.send_header('Last-Modified', last_modified)
        req.send_header('Content-Length', len(content))
        req.write(content)
Example #33
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 #34
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 #35
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 #36
0
    def process_request(self, req):
        req.perm('pastebin').assert_permission('PASTEBIN_VIEW')
        add_stylesheet(req, 'pastebin/css/pastebin.css')
        add_stylesheet(req, 'common/css/code.css')

        if (not req.args):
            req.redirect(req.href.pastebin())

        # new post
        if req.args['new_paste']:
            title = req.args.get('title', 'untitled')
            author = req.args.get('author', req.authname)
            mimetype = req.args.get('mimetype', 'text/plain')
            data = req.args.get('data', '')
            error = False

            # check if we reply to a paste
            if 'reply' in req.args and req.args['reply'].isdigit():
                replyto = req.args['reply']
                paste = Paste(self.env, id=replyto)
                if paste:
                    title = paste.title
                    if not title.startswith('Re:'):
                        title = 'Re: ' + title
                    data = paste.data
                    mimetype = paste.mimetype
            else:
                replyto = '0'

            if 'delete' in req.args and req.args['delete'].isdigit():
                req.perm('pastebin').assert_permission('PASTEBIN_DELETE')
                delete = req.args['delete']
                paste = Paste(self.env, id=delete)
                if paste:
                    paste.delete()
                    data = {
                        'mode': 'delete',
                        'paste': paste,
                    }
                    return 'pastebin.html', data, None

            if req.method == 'POST':
                req.perm('pastebin').assert_permission('PASTEBIN_CREATE')
                if not data.strip():
                    error = True
                else:
                    paste = Paste(self.env,
                                  title=title,
                                  author=author,
                                  mimetype=mimetype,
                                  data=data)
                    paste.save()
                    req.redirect(req.href.pastebin(paste.id))

            data = {
                'mode': 'new',
                'replyto': replyto,
                'mimetypes': self._get_mimetypes(),
                'mimetype': mimetype,
                'title': title,
                'author': author,
                'error': error,
                'data': data,
                'recent': get_pastes(env=self.env, number=self.max_recent)
            }

        # show post
        else:
            req.perm('pastebin').assert_permission('PASTEBIN_VIEW')

            paste = Paste(self.env, req.args['paste_id'])

            # text format
            if req.args.get('format') in ('txt',
                                          'raw') and self.enable_other_formats:
                if req.args['format'] == 'txt':
                    mimetype = 'text/plain'
                else:
                    mimetype = paste.mimetype

                if self._download_allowed(mimetype):
                    self.env.log.info("*** serving download")
                    content = paste.data
                    req.send_response(200)
                    req.send_header('Content-Type', mimetype)
                    req.send_header('Content-Length', len(content))
                    req.send_header('Last-Modified', http_date(paste.time))
                    req.end_headers()
                    if isinstance(content, unicode):
                        content = content.encode('utf-8')
                    req.write(content)
                    return
                else:
                    self.env.log.info("*** download denied")

            data = {
                'mode': 'show',
                'paste': paste,
                'highlighter': self._get_highlighter(paste.mimetype),
            }

            if self.enable_other_formats:
                if self._download_allowed(paste.mimetype):
                    # add link for original format
                    raw_href = req.href.pastebin(paste.id, format='raw')
                    add_link(req, 'alternate', raw_href, _('Original Format'),
                             paste.mimetype)

                if paste.mimetype != 'text/plain' and self._download_allowed(
                        'text/plain'):
                    # add link for text format
                    plain_href = req.href.pastebin(paste.id, format='txt')
                    add_link(req, 'alternate', plain_href, _('Plain Text'),
                             'text/plain')

        return 'pastebin.html', data, None
Example #37
0
    def process_request(self, req):
        req.perm('pastebin').assert_permission('PASTEBIN_VIEW')
        add_stylesheet(req, 'pastebin/css/pastebin.css')
        add_stylesheet(req, 'common/css/code.css')

        if (not req.args):
            req.redirect(req.href.pastebin())
        
        # new post
        if req.args['new_paste']:
            title = req.args.get('title', 'untitled')
            author = req.args.get('author', req.authname)
            mimetype = req.args.get('mimetype', 'text/plain')
            data = req.args.get('data', '')
            error = False

            # check if we reply to a paste
            if 'reply' in req.args and req.args['reply'].isdigit():
                replyto = req.args['reply']
                paste = Paste(self.env, id=replyto)
                if paste:
                    title = paste.title
                    if not title.startswith('Re:'):
                        title = 'Re: ' + title
                    data = paste.data
                    mimetype = paste.mimetype
            else:
                replyto = '0'

            if 'delete' in req.args and req.args['delete'].isdigit():
                req.perm('pastebin').assert_permission('PASTEBIN_DELETE')
                delete = req.args['delete']
                paste = Paste(self.env, id=delete)
                if paste:
                    paste.delete()
                    data = {
                        'mode':         'delete',
                        'paste':        paste,
                    }
                    return 'pastebin.html', data, None

            if req.method == 'POST':
                req.perm('pastebin').assert_permission('PASTEBIN_CREATE')
                if not data.strip():
                    error = True
                else:
                    paste = Paste(self.env,
                        title=title,
                        author=author,
                        mimetype=mimetype,
                        data=data
                    )
                    paste.save()
                    req.redirect(req.href.pastebin(paste.id))

            data = {
                'mode':             'new',
                'replyto':          replyto,
                'mimetypes':        self._get_mimetypes(),
                'mimetype':         mimetype,
                'title':            title,
                'author':           author,
                'error':            error,
                'data':             data,
                'recent':           get_pastes(env=self.env, number=self.max_recent)
            }

        # show post
        else:
            req.perm('pastebin').assert_permission('PASTEBIN_VIEW')

            paste = Paste(self.env, req.args['paste_id'])

            # text format
            if req.args.get('format') in ('txt', 'raw') and self.enable_other_formats:
                if req.args['format'] == 'txt':
                    mimetype = 'text/plain'
                else:
                    mimetype = paste.mimetype

                if self._download_allowed(mimetype):
                    self.env.log.info("*** serving download")
                    content = paste.data
                    req.send_response(200)
                    req.send_header('Content-Type', mimetype)
                    req.send_header('Content-Length', len(content))
                    req.send_header('Last-Modified', http_date(paste.time))
                    req.end_headers()
                    if isinstance(content, unicode):
                        content = content.encode('utf-8')
                    req.write(content)
                    return
                else:
                    self.env.log.info("*** download denied")

            data = {
                'mode':             'show',
                'paste':            paste,
                'highlighter':      self._get_highlighter(paste.mimetype),
            }

            if self.enable_other_formats:
                if self._download_allowed(paste.mimetype):
                    # add link for original format
                    raw_href = req.href.pastebin(paste.id, format='raw')
                    add_link(req, 'alternate', raw_href, _('Original Format'), paste.mimetype)

                if paste.mimetype != 'text/plain' and self._download_allowed('text/plain'):
                    # add link for text format
                    plain_href = req.href.pastebin(paste.id, format='txt')
                    add_link(req, 'alternate', plain_href, _('Plain Text'), 'text/plain')

        return 'pastebin.html', data, None
Example #38
0
def render_zip(req, filename, repos, root_node, iter_nodes):
    """Send a ZIP file containing the data corresponding to the `nodes`
    iterable.

    :type root_node: `~trac.versioncontrol.api.Node`
    :param root_node: optional ancestor for all the *nodes*

    :param iter_nodes: callable taking the optional *root_node* as input
                       and generating the `~trac.versioncontrol.api.Node`
                       for which the content should be added into the zip.
    """
    req.send_response(200)
    req.send_header('Content-Type', 'application/zip')
    req.send_header('Content-Disposition',
                    content_disposition('inline', filename))
    if root_node:
        req.send_header('Last-Modified', http_date(root_node.last_modified))
        root_path = root_node.path.rstrip('/')
    else:
        root_path = ''
    if root_path:
        root_path += '/'
        root_name = root_node.name + '/'
    else:
        root_name = ''
    root_len = len(root_path)
    req.end_headers()

    def write_partial(fileobj, start):
        end = fileobj.tell()
        fileobj.seek(start, 0)
        remaining = end - start
        while remaining > 0:
            chunk = fileobj.read(min(remaining, 4096))
            req.write(chunk)
            remaining -= len(chunk)
        fileobj.seek(end, 0)
        return end

    pos = 0
    with TemporaryFile(prefix='trac-', suffix='.zip') as fileobj:
        with ZipFile(fileobj, 'w', ZIP_DEFLATED) as zipfile:
            for node in iter_nodes(root_node):
                if node is root_node:
                    continue
                path = node.path.strip('/')
                assert path.startswith(root_path)
                path = root_name + path[root_len:]
                kwargs = {'mtime': node.last_modified}
                data = None
                if node.isfile:
                    with content_closing(
                            node.get_processed_content(eol_hint='CRLF')) \
                            as content:
                        data = content.read()
                    props = node.get_properties()
                    # Subversion specific
                    if 'svn:special' in props and data.startswith('link '):
                        data = data[5:]
                        kwargs['symlink'] = True
                    if 'svn:executable' in props:
                        kwargs['executable'] = True
                elif node.isdir and path:
                    kwargs['dir'] = True
                    data = ''
                if data is not None:
                    zipfile.writestr(create_zipinfo(path, **kwargs), data)
                    pos = write_partial(fileobj, pos)
        write_partial(fileobj, pos)
    raise RequestDone
Example #39
0
                elif column == 'reporter':
                    if cell.find('@') != -1:
                        value['rss'] = cell
                    elif cell in email_map:
                        value['rss'] = email_map[cell]
                elif column == 'report':
                    value['report_href'] = req.href.report(cell)
                elif column in ('time', 'date','changetime', 'created', 'modified'):
                    if cell == 'None':
                        value['date'] = value['time'] = cell
                        value['datetime'] = value['gmt'] = cell
                    else:
                        value['date'] = format_date(cell)
                        value['time'] = format_time(cell)
                        value['datetime'] = format_datetime(cell)
                        value['gmt'] = http_date(cell)
                prefix = 'report.items.%d.%s' % (row_idx, unicode(column))
                req.hdf[prefix] = unicode(cell)
                for key in value.keys():
                    req.hdf[prefix + '.' + key] = value[key]

                col_idx += 1
            row_idx += 1
        req.hdf['report.numrows'] = row_idx

        if format == 'rss':
            return 'report_rss.cs', 'application/rss+xml'
        elif format == 'csv':
            filename = id and 'report_%s.csv' % id or 'report.csv'
            self._render_csv(req, cols, rows, mimetype='text/csv',
                             filename=filename)
Example #40
0
    def _render_file(self, req, context, repos, node, rev=None):
        req.perm(node.resource).require('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',
                            'text/plain' if format == 'txt' else mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified', http_date(node.last_modified))
            if rev is None:
                req.send_header('Pragma', 'no-cache')
                req.send_header('Cache-Control', 'no-cache')
                req.send_header('Expires', 'Fri, 01 Jan 1999 00:00:00 GMT')
            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.created_rev)

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != 'text/plain':
                plain_href = req.href.browser(repos.reponame or None,
                                              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.export(rev or repos.youngest_rev,
                                       repos.reponame or None, node.path)
            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

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

            annotations = ['lineno']
            annotate = req.args.get('annotate')
            if annotate:
                annotations.insert(0, annotate)
            preview_data = mimeview.preview_data(context, node.get_content(),
                                                 node.get_content_length(),
                                                 mime_type, node.created_path,
                                                 raw_href,
                                                 annotations=annotations,
                                                 force_source=bool(annotate))
            return {
                'changeset': changeset,
                'size': node.content_length,
                'preview': preview_data,
                'annotate': annotate,
                }
Example #41
0
    def process_request(self, req):
        req.perm.assert_permission("LOG_VIEW")

        mode = req.args.get("mode", "stop_on_copy")
        path = req.args.get("path", "/")
        rev = req.args.get("rev")
        stop_rev = req.args.get("stop_rev")
        format = req.args.get("format")
        verbose = req.args.get("verbose")
        limit = LOG_LIMIT

        repos = self.env.get_repository(req.authname)
        normpath = repos.normalize_path(path)
        rev = unicode(repos.normalize_rev(rev))
        if stop_rev:
            stop_rev = unicode(repos.normalize_rev(stop_rev))
            if repos.rev_older_than(rev, stop_rev):
                rev, stop_rev = stop_rev, rev

        req.hdf["title"] = path + " (log)"
        req.hdf["log"] = {
            "mode": mode,
            "path": path,
            "rev": rev,
            "verbose": verbose,
            "stop_rev": stop_rev,
            "browser_href": req.href.browser(path),
            "changeset_href": req.href.changeset(),
            "log_href": req.href.log(path, rev=rev),
        }

        path_links = get_path_links(req.href, path, rev)
        req.hdf["log.path"] = path_links
        if path_links:
            add_link(req, "up", path_links[-1]["href"], u"Répertoire parent")

        # The `history()` method depends on the mode:
        #  * for ''stop on copy'' and ''follow copies'', it's `Node.history()`
        #  * for ''show only add, delete'' it's`Repository.get_path_history()`
        if mode == "path_history":

            def history(limit):
                for h in repos.get_path_history(path, rev, limit):
                    yield h

        else:
            history = get_existing_node(req, repos, path, rev).get_history

        # -- retrieve history, asking for limit+1 results
        info = []
        previous_path = repos.normalize_path(path)
        for old_path, old_rev, old_chg in history(limit + 1):
            if stop_rev and repos.rev_older_than(old_rev, stop_rev):
                break
            old_path = repos.normalize_path(old_path)
            item = {
                "rev": str(old_rev),
                "path": old_path,
                "log_href": req.href.log(old_path, rev=old_rev),
                "browser_href": req.href.browser(old_path, rev=old_rev),
                "changeset_href": req.href.changeset(old_rev),
                "restricted_href": req.href.changeset(old_rev, new_path=old_path),
                "change": old_chg,
            }
            if not (mode == "path_history" and old_chg == Changeset.EDIT):
                info.append(item)
            if old_path and old_path != previous_path and not (mode == "path_history" and old_path == normpath):
                item["copyfrom_path"] = old_path
                if mode == "stop_on_copy":
                    break
            if len(info) > limit:  # we want limit+1 entries
                break
            previous_path = old_path
        if info == []:
            # FIXME: we should send a 404 error here
            raise TracError(
                u"Le fichier ou le répertoire '%s' n'existe pas "
                u"en révision %s ou pour toute révision précédente." % (path, rev),
                u"Chemin inexistant",
            )

        def make_log_href(path, **args):
            link_rev = rev
            if rev == str(repos.youngest_rev):
                link_rev = None
            params = {"rev": link_rev, "mode": mode, "limit": limit}
            params.update(args)
            if verbose:
                params["verbose"] = verbose
            return req.href.log(path, **params)

        if len(info) == limit + 1:  # limit+1 reached, there _might_ be some more
            next_rev = info[-1]["rev"]
            next_path = info[-1]["path"]
            add_link(
                req,
                "next",
                make_log_href(next_path, rev=next_rev),
                u"Journal des révisions (repartant de %s, rév. %s)" % (next_path, next_rev),
            )
            # now, only show 'limit' results
            del info[-1]

        req.hdf["log.items"] = info

        revs = [i["rev"] for i in info]
        changes = get_changes(self.env, repos, revs, verbose, req, format)
        if format == "rss":
            # Get the email addresses of all known users
            email_map = {}
            for username, name, email in self.env.get_known_users():
                if email:
                    email_map[username] = email
            for cs in changes.values():
                # For RSS, author must be an email address
                author = cs["author"]
                author_email = ""
                if "@" in author:
                    author_email = author
                elif email_map.has_key(author):
                    author_email = email_map[author]
                cs["author"] = author_email
                cs["date"] = http_date(cs["date_seconds"])
        elif format == "changelog":
            for rev in revs:
                changeset = repos.get_changeset(rev)
                cs = changes[rev]
                cs["message"] = wrap(changeset.message, 70, initial_indent="\t", subsequent_indent="\t")
                files = []
                actions = []
                for path, kind, chg, bpath, brev in changeset.get_changes():
                    files.append(chg == Changeset.DELETE and bpath or path)
                    actions.append(chg)
                cs["files"] = files
                cs["actions"] = actions
        req.hdf["log.changes"] = changes

        if req.args.get("format") == "changelog":
            return "log_changelog.cs", "text/plain"
        elif req.args.get("format") == "rss":
            return "log_rss.cs", "application/rss+xml"

        add_stylesheet(req, "common/css/browser.css")
        add_stylesheet(req, "common/css/diff.css")

        rss_href = make_log_href(path, format="rss", stop_rev=stop_rev)
        add_link(req, "alternate", rss_href, "RSS Feed", "application/rss+xml", "rss")
        changelog_href = make_log_href(path, format="changelog", stop_rev=stop_rev)
        add_link(req, "alternate", changelog_href, "ChangeLog", "text/plain")

        return "log.cs", None