示例#1
0
def open_environment(env_path, mpr):
    env = Environment.Environment(env_path)
    version = env.get_version()
    if version < Environment.db_version:
        raise TracError('The Trac environment needs to be upgraded. '
                        'Run "trac-admin %s upgrade"' % env_path)
    elif version > Environment.db_version:
        raise TracError('Unknown Trac Environment version (%d).' % version)

    env.href = Href.Href(mpr.cgi_location)
    env.abs_href = Href.Href(mpr.base_url)

    return env
示例#2
0
def open_environment():
    env_path = os.getenv('TRAC_ENV')
    if not env_path:
        raise EnvironmentError, \
              'Missing environment variable "TRAC_ENV". Trac ' \
              'requires this variable to point to a valid Trac Environment.'

    env = Environment.Environment(env_path)
    version = env.get_version()
    if version < Environment.db_version:
        raise TracError('The Trac Environment needs to be upgraded. '
                        'Run "trac-admin %s upgrade"' % env_path)
    elif version > Environment.db_version:
        raise TracError('Unknown Trac Environment version (%d).' % version)
    return env
示例#3
0
 def get_session(self, sid):
     self.sid = sid
     curs = self.db.cursor()
     curs.execute("SELECT username,var_name,var_value FROM session"
                 " WHERE sid=%s", self.sid)
     rows = curs.fetchall()
     if (not rows                              # No session data yet
         or rows[0][0] == 'anonymous'          # Anon session
         or rows[0][0] == self.req.authname):  # Session is mine
         for u,k,v in rows:
             self.vars[k] = v
         self.update_sess_time()
         self.bake_cookie()
         self.populate_hdf()
         return
     if self.req.authname == 'anonymous':
         err = ('Session cookie requires authentication. <p>'
                'Please choose action:</p>'
                '<ul><li><a href="%s">Log in and continue session</a></li>'
                '<li><a href="%s?newsession=1">Create new session (no login required)</a></li>'
                '</ul>'
                % (self.env.href.login(), self.env.href.settings()))
     else:
         err = ('Session belongs to another authenticated user.'
                '<p><a href="%s?newsession=1">'
                'Create new session</a></p>' % self.env.href.settings())
     raise TracError(err, 'Error accessing authenticated session')
示例#4
0
    def commit(self, author, comment, remote_addr):
        if self.new:
            self.perm.assert_permission(perm.WIKI_CREATE)
        else:
            self.perm.assert_permission(perm.WIKI_MODIFY)
        if self.readonly:
            self.perm.assert_permission(perm.WIKI_ADMIN)

        cursor = self.db.cursor()
        if not self.modified and self.readonly != self.old_readonly:
            cursor.execute(
                'UPDATE wiki SET readonly=%s WHERE name=%s and VERSION=%s',
                self.readonly, self.name, self.version - 1)
            self.db.commit()
            self.old_readonly = self.readonly
        elif self.modified:
            cursor.execute(
                'INSERT INTO WIKI '
                '(name, version, time, author, ipnr, text, comment, readonly) '
                'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)', self.name,
                self.version, int(time.time()), author, remote_addr, self.text,
                comment, self.readonly)
            self.db.commit()
            self.old_readonly = self.readonly
            self.modified = 0
        else:
            del cursor
            raise TracError('Page not modified')
示例#5
0
    def generate_diff(self, pagename, version):
        import Diff
        Diff.get_options(self.env, self.req, self.args)
        if self.args.has_key('update'):
            self.req.redirect(self.env.href.wiki(pagename, version, 1))

        cursor = self.db.cursor()
        cursor.execute(
            'SELECT text,author,comment,time FROM wiki '
            'WHERE name=%s AND (version=%s or version=%s)'
            'ORDER BY version ASC', pagename, version - 1, version)
        res = cursor.fetchall()
        if not res:
            raise TracError(
                'Version %d of page "%s" not found.' % (version, pagename),
                'Page Not Found')

        if len(res) == 1:
            old = ''
        else:
            old = res[0][0].splitlines()
        new = res[-1][0].splitlines()
        author = res[-1][1] or ''
        comment = res[-1][2] or ''
        time_str = time.strftime('%c', time.localtime(int(res[-1][3])))
        self.req.hdf.setValue('wiki.version', str(version))
        self.req.hdf.setValue('wiki.diff.time', time_str)
        self.req.hdf.setValue('wiki.diff.author', escape(author))
        self.req.hdf.setValue('wiki.diff.comment', escape(comment))

        builder = Diff.HDFBuilder(self.req.hdf, 'wiki.diff')
        builder.writeline('header %s %d | %s %d redaeh' %
                          (pagename, version - 1, pagename, version))
        builder.writeline('@@ -1,%d +1,%d @@' % (len(old), len(new)))
        try:
            for line in difflib.Differ().compare(old, new):
                if line != '  ':
                    builder.writeline(line)
        except AttributeError:
            raise TracError('Python >= 2.2 is required for diff support.')
        builder.close()
示例#6
0
 def create_milestone(self, name, date=0, descr=''):
     self.perm.assert_permission(perm.MILESTONE_CREATE)
     if not name:
         raise TracError('You must provide a name for the milestone.',
                         'Required Field Missing')
     cursor = self.db.cursor()
     self.log.debug("Creating new milestone '%s'" % name)
     cursor.execute(
         "INSERT INTO milestone (id, name, time, descr) "
         "VALUES (NULL, %s, %d, %s)", name, date, descr)
     self.db.commit()
     self.req.redirect(self.env.href.milestone(name))
示例#7
0
 def change_sid(self, newsid):
     if newsid == self.sid:
         return
     curs = self.db.cursor()
     curs.execute("SELECT sid FROM session WHERE sid=%s", newsid)
     if curs.fetchone():
         raise TracError("Session '%s' already exists.<br />"
                         "Please choose a different session id." % newsid,
                         "Error renaming session")
     curs.execute("UPDATE session SET sid=%s WHERE sid=%s",
                  newsid, self.sid)
     self.db.commit()
     self.sid = newsid
     self.bake_cookie()
示例#8
0
 def parse_date(self, datestr):
     seconds = None
     datestr = datestr.strip()
     for format in [
             '%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y'
     ]:
         try:
             date = time.strptime(datestr, format)
             seconds = time.mktime(date)
             break
         except ValueError:
             continue
     if seconds == None:
         raise TracError('%s is not a known date format.' % datestr,
                         'Invalid Date Format')
     return seconds
示例#9
0
 def get_milestone(self, name):
     cursor = self.db.cursor()
     cursor.execute(
         "SELECT name, time, descr FROM milestone "
         "WHERE name = %s ORDER BY time, name", name)
     row = cursor.fetchone()
     cursor.close()
     if not row:
         raise TracError('Milestone %s does not exist.' % name,
                         'Invalid Milestone Number')
     milestone = {'name': row['name']}
     descr = row['descr']
     if descr:
         milestone['descr_source'] = descr
         milestone['descr'] = wiki_to_html(descr, self.req.hdf, self.env,
                                           self.db)
     t = row['time'] and int(row['time'])
     if t > 0:
         milestone['date'] = time.strftime('%x', time.localtime(t))
     return milestone
示例#10
0
    def notify(self, resid, subject):
        self.subject = subject

        enabled = self.env.get_config('notification', 'smtp_enabled', '0')
        if not enabled.lower() in TRUE:
            return
        self.smtp_server = self.env.get_config('notification', 'smtp_server',
                                               self.smtp_server)
        self.from_email = self.env.get_config('notification', 'smtp_from', '')
        self.replyto_email = self.env.get_config('notification',
                                                 'smtp_replyto',
                                                 self.from_email)
        self.from_email = self.from_email or self.replyto_email
        if not self.from_email and not self.replyto_email:
            raise TracError(
                'Unable to send email due to identity crisis. <br />'
                'Both <b>notification.from</b> and'
                ' <b>notification.reply_to</b> are unspecified'
                ' in configuration.', 'SMTP Notification Error')
        Notify.notify(self, resid)
示例#11
0
 def save_milestone(self, id):
     self.perm.assert_permission(perm.MILESTONE_MODIFY)
     if self.args.has_key('save'):
         name = self.args.get('name', '')
         if not name:
             raise TracError('You must provide a name for the milestone.',
                             'Required Field Missing')
         datemode = self.args.get('datemode', 'manual')
         if datemode == 'now':
             date = int(time.time())
         else:
             datestr = self.args.get('date', '')
             date = 0
             if datestr:
                 date = self.parse_date(datestr)
         descr = self.args.get('descr', '')
         if not id:
             self.create_milestone(name, date, descr)
         else:
             self.update_milestone(id, name, date, descr)
     elif id:
         self.req.redirect(self.env.href.milestone(id))
     else:
         self.req.redirect(self.env.href.roadmap())
示例#12
0
    def render(self):
        name = self.args.get('page', 'WikiStart')
        author = self.args.get('author', get_reporter_id(self.req))
        edit_version = self.args.get('edit_version', None)
        delete_ver = self.args.get('delete_ver', None)
        delete_page = self.args.get('delete_page', None)
        comment = self.args.get('comment', '')
        save = self.args.get('save', None)
        edit = self.args.get('edit', None)
        diff = self.args.get('diff', None)
        cancel = self.args.get('cancel', None)
        preview = self.args.get('preview', None)
        history = self.args.get('history', None)
        version = int(self.args.get('version', 0))
        readonly = self.args.get('readonly', None)

        # Ask web spiders to not index old version
        if diff or version:
            self.req.hdf.setValue('html.norobots', '1')

        if cancel:
            self.req.redirect(self.env.href.wiki(name))
            # Not reached

        if delete_ver and edit_version and name:
            # Delete only a specific page version
            self.perm.assert_permission(perm.WIKI_DELETE)
            cursor = self.db.cursor()
            cursor.execute('DELETE FROM wiki WHERE name=%s and version=%s',
                           name, int(edit_version))
            self.db.commit()
            self.log.info('Deleted version %d of page %s' %
                          (int(edit_version), name))
            if int(edit_version) > 1:
                self.req.redirect(self.env.href.wiki(name))
            else:
                # Delete orphaned attachments
                for attachment in self.env.get_attachments(
                        self.db, 'wiki', name):
                    self.env.delete_attachment(self.db, 'wiki', name,
                                               attachment[0])
                self.req.redirect(self.env.href.wiki())
            # Not reached

        if delete_page and name:
            # Delete a wiki page completely
            self.perm.assert_permission(perm.WIKI_DELETE)
            cursor = self.db.cursor()
            cursor.execute('DELETE FROM wiki WHERE name=%s', name)
            self.db.commit()
            self.log.info('Deleted version %d of page ' + name)
            # Delete orphaned attachments
            for attachment in self.env.get_attachments(self.db, 'wiki', name):
                self.env.delete_attachment(self.db, 'wiki', name,
                                           attachment[0])
            self.req.redirect(self.env.href.wiki())
            # Not reached

        self.req.hdf.setValue('wiki.name', escape(name))
        self.req.hdf.setValue('wiki.author', escape(author))
        self.req.hdf.setValue('wiki.comment', escape(comment))
        # Workaround so that we can attach files to wiki pages
        # even if the page name contains a '/'
        self.req.hdf.setValue('wiki.namedoublequoted',
                              urllib.quote(urllib.quote(name, '')))

        session = Session(self.env, self.req)
        editrows = self.args.get('editrows')
        if editrows:
            self.req.hdf.setValue('wiki.edit_rows', editrows)
            pref = session.get('wiki_editrows', '20')
            if editrows != pref:
                session.set_var('wiki_editrows', editrows)
        else:
            self.req.hdf.setValue('wiki.edit_rows',
                                  session.get('wiki_editrows', '20'))

        if save:
            self.req.hdf.setValue('wiki.action', 'save')
        elif edit:
            self.perm.assert_permission(perm.WIKI_MODIFY)
            self.req.hdf.setValue('wiki.action', 'edit')
            self.req.hdf.setValue('title', escape(name) + ' (edit)')
        elif preview:
            self.req.hdf.setValue('wiki.action', 'preview')
            self.req.hdf.setValue('wiki.scroll_bar_pos',
                                  self.args.get('scroll_bar_pos', ''))
            self.req.hdf.setValue('title', escape(name) + ' (preview)')
        elif diff and version > 0:
            self.req.hdf.setValue('wiki.action', 'diff')
            self.generate_diff(name, version)
            self.req.hdf.setValue('title', escape(name) + ' (diff)')
        elif history:
            self.req.hdf.setValue('wiki.action', 'history')
            self.generate_history(name)
            self.req.hdf.setValue('title', escape(name) + ' (history)')
        else:
            self.perm.assert_permission(perm.WIKI_VIEW)
            if version:
                self.add_link('alternate',
                              '?version=%d&amp;format=txt' % version,
                              'Plain Text', 'text/plain')
            else:
                self.add_link('alternate', '?format=txt', 'Plain Text',
                              'text/plain')
            if self.args.has_key('text'):
                del self.args['text']
            self.req.hdf.setValue('wiki.action', 'view')
            if name == 'WikiStart':
                self.req.hdf.setValue('title', '')
            else:
                self.req.hdf.setValue('title', escape(name))
            self.env.get_attachments_hdf(self.db, 'wiki', name, self.req.hdf,
                                         'wiki.attachments')

        self.page = WikiPage(name, version, self.perm, self.db)
        if self.args.has_key('text'):
            self.page.set_content(self.args.get('text'))
        else:
            self.page.modified = 0

        # Modify the read-only flag if it has been changed and the user is WIKI_ADMIN
        if save and self.perm.has_permission(perm.WIKI_ADMIN):
            if readonly:
                self.page.readonly = 1
            else:
                self.page.readonly = 0

        self.req.hdf.setValue('wiki.readonly', str(self.page.readonly))
        # We store the page version when we start editing a page.
        # This way we can stop users from saving changes if they are
        # not based on the latest version any more
        if edit_version:
            self.req.hdf.setValue('wiki.edit_version', edit_version)
        else:
            self.req.hdf.setValue('wiki.edit_version', str(self.page.version))

        if save and edit_version != str(self.page.version - 1):
            raise TracError('Sorry, Cannot create new version, this page has '
                            'already been modified by someone else.')

        if save:
            self.page.commit(author, comment, self.req.remote_addr)
            self.req.redirect(self.env.href.wiki(self.page.name))

        self.req.hdf.setValue('wiki.current_href',
                              escape(self.env.href.wiki(self.page.name)))
        self.req.hdf.setValue(
            'wiki.history_href',
            escape(self.env.href.wiki(self.page.name, history=1)))
        self.req.hdf.setValue('wiki.page_name', escape(self.page.name))
        self.req.hdf.setValue('wiki.page_source', escape(self.page.text))
        out = StringIO.StringIO()
        Formatter(self.req.hdf, self.env, self.db).format(self.page.text, out)
        self.req.hdf.setValue('wiki.page_html', out.getvalue())
示例#13
0
    def perform_query (self, query, changeset, tickets, wiki, page=0):
        if not query:
            return ([], 0)
        keywords = query.split(' ')

        if changeset:
            changeset = self.perm.has_permission(perm.CHANGESET_VIEW)
        if tickets:
            tickets = self.perm.has_permission(perm.TICKET_VIEW)
        if wiki:
            wiki = self.perm.has_permission(perm.WIKI_VIEW)

        if changeset == tickets == wiki == 0:
            return ([], 0)

        if len(keywords) == 1:
            kwd = keywords[0]
            redir = None
            # Prepending a '!' disables quickjump feature
            if kwd[0] == '!':
                keywords[0] = kwd[1:]
                query = query[1:]
                self.req.hdf.setValue('search.q', query)
            # Ticket quickjump
            elif kwd[0] == '#' and kwd[1:].isdigit():
                redir = self.env.href.ticket(kwd[1:])
            # Changeset quickjump
            elif kwd[0] == '[' and kwd[-1] == ']' and kwd[1:-1].isdigit():
                redir = self.env.href.changeset(kwd[1:-1])
            # Report quickjump
            elif kwd[0] == '{' and kwd[-1] == '}' and kwd[1:-1].isdigit():
                redir = self.env.href.report(kwd[1:-1])
            elif kwd[0].isupper() and kwd[1].islower():
                r = "((^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)"
                if re.match (r, kwd):
                    redir = self.env.href.wiki(kwd)
            if redir:
                self.req.hdf.setValue('search.q', '')
                self.req.redirect(redir)
            elif len(query) < 3:
                raise TracError('Search query too short. '
                                'Query must be at least 3 characters long.',
                                'Search Error')

        cursor = self.db.cursor ()

        q = []
        if changeset:
            q.append('SELECT 1 as type, message AS title, message, author, '
                     ' \'\' AS keywords, rev AS data, time,0 AS ver'
                     ' FROM revision WHERE %s OR %s' % 
                     (self.query_to_sql(query, 'message'),
                      self.query_to_sql(query, 'author')))
        if tickets:
            q.append('SELECT DISTINCT 2 as type, a.summary AS title, '
                     ' a.description AS message, a.reporter AS author, '
                     ' a.keywords as keywords, a.id AS data, a.time as time, 0 AS ver'
                     ' FROM ticket a LEFT JOIN ticket_change b ON a.id = b.ticket'
                     ' WHERE (b.field=\'comment\' AND %s ) OR'
                     ' %s OR %s OR %s OR %s OR %s' %
                      (self.query_to_sql(query, 'b.newvalue'),
                       self.query_to_sql(query, 'summary'),
                       self.query_to_sql(query, 'keywords'),
                       self.query_to_sql(query, 'description'),
                       self.query_to_sql(query, 'reporter'),
                       self.query_to_sql(query, 'cc')))
        if wiki:
            q.append('SELECT 3 as type, text AS title, text AS message,'
                     ' author, \'\' AS keywords, w1.name AS data, time,'
                     ' w1.version as ver'
                     ' FROM wiki w1, '
                     ' (SELECT name,max(version) AS ver '
                     '    FROM wiki GROUP BY name) w2'
                     ' WHERE w1.version = w2.ver AND w1.name = w2.name  AND'
                     ' (%s OR %s OR %s) ' %
                     (self.query_to_sql(query, 'w1.name'),
                      self.query_to_sql(query, 'w1.author'),
                      self.query_to_sql(query, 'w1.text')))

        if not q: return []

        q_str = string.join(q, ' UNION ALL ')
        q_str += ' ORDER BY 7 DESC LIMIT %d OFFSET %d' % \
                 (self.RESULTS_PER_PAGE + 1, self.RESULTS_PER_PAGE * page)

        self.log.debug("SQL Query: %s" % q_str)
        cursor.execute(q_str)

        # Make the data more HDF-friendly
        info = []
        more = 0
        while 1:
            row = cursor.fetchone()
            if not row:
                break
            if len(info) == self.RESULTS_PER_PAGE:
                more = 1
                break
            msg = row['message']
            t = time.localtime(int(row['time']))
            item = {'type': int(row['type']),
                    'keywords': row['keywords'] or '',
                    'data': row['data'],
                    'title': escape(row['title'] or ''),
                    'datetime' : time.strftime('%c', t),
                    'author': escape(row['author'])}
            if item['type'] == 1:
                item['changeset_href'] = self.env.href.changeset(int(row['data']))
            elif item['type'] == 2:
                item['ticket_href'] = self.env.href.ticket(int(row['data']))
            elif item['type'] == 3:
                item['wiki_href'] = self.env.href.wiki(row['data'])

            item['shortmsg'] = escape(shorten_line(msg))
            item['message'] = escape(self.shorten_result(msg, keywords))
            info.append(item)
        return info, more