def render_confirm_delete(self, id): self.perm.assert_permission(perm.REPORT_DELETE) cursor = self.db.cursor() cursor.execute('SELECT title FROM report WHERE id = %s', id) row = cursor.fetchone() if not row: raise util.TracError('Report %s does not exist.' % id, 'Invalid Report Number') self.req.hdf.setValue('title', 'Delete Report {%s} %s' % (id, row['title'])) self.req.hdf.setValue('report.mode', 'delete') self.req.hdf.setValue('report.id', str(id)) self.req.hdf.setValue('report.title', row['title'])
def execute_report(self, sql, args): cursor = self.db.cursor() sql = self.sql_sub_vars(sql, args) if not sql: raise util.TracError('Report %s has no SQL query.' % id) cursor.execute(sql) if sql.find('__group__') == -1: self.req.hdf.setValue('report.sorting.enabled', '1') # FIXME: fetchall should probably not be used. info = cursor.fetchall() cols = cursor.rs.col_defs # Escape the values so that they are safe to have as html parameters #info = map(lambda row: map(lambda x: escape(x), row), info) return [cols, info]
def save_changes(self, id): self.perm.assert_permission(perm.TICKET_MODIFY) ticket = Ticket(self.db, id) if not self.args.get('summary'): raise util.TracError('Tickets must contain Summary.') if self.args.has_key('description'): self.perm.assert_permission(perm.TICKET_ADMIN) if self.args.has_key('reporter'): self.perm.assert_permission(perm.TICKET_ADMIN) # TODO: this should not be hard-coded like this action = self.args.get('action', None) if action == 'accept': ticket['status'] = 'assigned' ticket['owner'] = self.req.authname if action == 'resolve': ticket['status'] = 'closed' ticket['resolution'] = self.args.get('resolve_resolution') elif action == 'reassign': ticket['owner'] = self.args.get('reassign_owner') ticket['status'] = 'new' elif action == 'reopen': ticket['status'] = 'reopened' ticket['resolution'] = '' ticket.populate(self.args) now = int(time.time()) ticket.save_changes(self.db, self.args.get('author', self.req.authname), self.args.get('comment'), when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=now) self.req.redirect(self.env.href.ticket(id))
def create_attachment(self, cnx, type, id, attachment, description, author, ipnr): # Maximum attachment size (in bytes) max_size = int(self.get_config('attachment', 'max_size', '262144')) if hasattr(attachment.file, 'fileno'): stat = os.fstat(attachment.file.fileno()) length = stat[6] else: length = attachment.file.len if length > max_size: raise util.TracError( 'Maximum attachment size: %d bytes' % max_size, 'Upload failed') dir = os.path.join(self.get_attachments_dir(), type, urllib.quote(id)) if not os.access(dir, os.F_OK): os.makedirs(dir) filename = attachment.filename.replace('\\', '/').replace(':', '/') filename = os.path.basename(filename) # We try to normalize the filename to utf-8 NFC if we can. # Files uploaded from OS X might be in NFD. if sys.version_info[0] > 2 or \ (sys.version_info[0] == 2 and sys.version_info[1] >= 3): filename = unicodedata.normalize('NFC', unicode(filename, 'utf-8')).encode('utf-8') filename = urllib.quote(filename) path, fd = util.create_unique_file(os.path.join(dir, filename)) filename = os.path.basename(path) filename = urllib.unquote(filename) cursor = cnx.cursor() cursor.execute( 'INSERT INTO attachment VALUES(%s,%s,%s,%s,%s,%s,%s,%s)', type, id, filename, length, int(time.time()), description, author, ipnr) shutil.copyfileobj(attachment.file, fd) self.log.info('New attachment: %s/%s/%s by %s', type, id, filename, author) cnx.commit() return filename
def get_info(self, id, args): cursor = self.db.cursor() if id == -1: # If no particular report was requested, display # a list of available reports instead title = 'Available Reports' sql = 'SELECT id AS report, title FROM report ORDER BY report' description = 'This is a list of reports available.' else: cursor.execute( 'SELECT title, sql, description from report ' ' WHERE id=%s', id) row = cursor.fetchone() if not row: raise util.TracError('Report %d does not exist.' % id, 'Invalid Report Number') title = row[0] or '' sql = row[1] description = row[2] or '' return [title, description, sql]
def create_ticket(self): if not self.args.get('summary'): raise util.TracError('Tickets must contain Summary.') ticket = Ticket() ticket.populate(self.args) ticket.setdefault('reporter', self.req.authname) # The owner field defaults to the component owner cursor = self.db.cursor() if ticket.get('component') and ticket.get('owner', '') == '': cursor.execute('SELECT owner FROM component ' 'WHERE name=%s', ticket['component']) owner = cursor.fetchone()[0] ticket['owner'] = owner tktid = ticket.insert(self.db) # Notify tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=1) self.req.redirect(self.env.href.ticket(tktid))
def render_diffs(self, editor_class=HtmlDiffEditor): """ generates a unified diff of the changes for a given changeset. the output is written to stdout. """ try: old_root = svn.fs.revision_root(self.fs_ptr, int(self.rev) - 1, self.pool) new_root = svn.fs.revision_root(self.fs_ptr, int(self.rev), self.pool) except svn.core.SubversionException: raise util.TracError('Invalid revision number: %d' % int(self.rev)) editor = editor_class(old_root, new_root, int(self.rev), self.req, self.args, self.env, self.authzperm) e_ptr, e_baton = svn.delta.make_editor(editor, self.pool) def authz_cb(root, path, pool): return self.authzperm.has_permission(path) and 1 or 0 svn.repos.svn_repos_dir_delta(old_root, '', '', new_root, '', e_ptr, e_baton, authz_cb, 0, 1, 0, 1, self.pool)
def _fetch_ticket(self, db, id): cursor = db.cursor() fetch = string.join(Ticket.std_fields, ',') cursor.execute(('SELECT %s FROM ticket ' % fetch) + 'WHERE id=%s', id) row = cursor.fetchone() cursor.close() if not row: raise util.TracError('Ticket %d does not exist.' % id, 'Invalid Ticket Number') self['id'] = id # Escape the values so that they are safe to have as html parameters for i in range(len(Ticket.std_fields)): self[Ticket.std_fields[i]] = row[i] or '' cursor = db.cursor() cursor.execute('SELECT name,value FROM ticket_custom WHERE ticket=%i', id) rows = cursor.fetchall() if rows: for r in rows: self['custom_' + r[0]] = r[1] self._forget_changes()
def get_info(self, path, revision, rev_specified): """ Extracts information for a given path and revision """ # We need to really make sure it's an ordinary string. The FieldStorage # class provided by modpython might give us some strange string-like object # that svn doesn't like. path = str(path) try: root = svn.fs.revision_root(self.fs_ptr, revision, self.pool) except svn.core.SubversionException: raise util.TracError('Invalid revision number: %d' % revision) node_type = svn.fs.check_path(root, path, self.pool) if not node_type in [svn.core.svn_node_dir, svn.core.svn_node_file]: raise util.TracError('"%s": no such file or directory in revision %d' \ % (path, revision), 'No such file or directory') # Redirect to the file module if the requested path happens # to point to a regular file if svn.fs.is_file(root, path, self.pool): if rev_specified: self.req.redirect(self.env.href.file(path, revision)) else: self.req.redirect(self.env.href.log(path)) entries = svn.fs.dir_entries(root, path, self.pool) info = [] for item in entries.keys(): fullpath = posixpath.join(path, item) is_dir = svn.fs.is_dir(root, fullpath, self.pool) if is_dir: name = item + '/' fullpath = fullpath + '/' else: name = item created_rev = svn.fs.node_created_rev(root, fullpath, self.pool) date = svn.fs.revision_prop(self.fs_ptr, created_rev, svn.core.SVN_PROP_REVISION_DATE, self.pool) if date: date_seconds = svn.core.svn_time_from_cstring(date, self.pool) / 1000000 date = time.strftime('%x %X', time.localtime(date_seconds)) else: date_seconds = 0 date = '' author = svn.fs.revision_prop(self.fs_ptr, created_rev, svn.core.SVN_PROP_REVISION_AUTHOR, self.pool) change = svn.fs.revision_prop(self.fs_ptr, created_rev, svn.core.SVN_PROP_REVISION_LOG, self.pool) item = { 'name' : name, 'fullpath' : fullpath, 'created_rev' : created_rev, 'date' : date, 'date_seconds' : date_seconds, 'age' : util.pretty_age(date_seconds), 'is_dir' : is_dir, 'author' : author, 'change' : wiki_to_oneliner(util.shorten_line(util.wiki_escape_newline(change)), self.req.hdf, self.env,self.db), 'permission' : self.authzperm.has_permission(fullpath) } if rev_specified: item['log_href'] = self.env.href.log(fullpath, revision) if is_dir: item['browser_href'] = self.env.href.browser(fullpath, revision) else: item['browser_href'] = self.env.href.file(fullpath, revision) else: item['log_href'] = self.env.href.log(fullpath) if is_dir: item['browser_href'] = self.env.href.browser(fullpath) else: item['browser_href'] = self.env.href.file(fullpath) info.append(item) return info
def render(self): FileCommon.render(self) self.view_form = 0 self.attachment_type = self.args.get('type', None) self.attachment_id = self.args.get('id', None) self.filename = self.args.get('filename', None) if self.filename: self.filename = os.path.basename(self.filename) if not self.attachment_type or not self.attachment_id: raise util.TracError('Unknown request') if self.filename and len(self.filename) > 0 and \ self.args.has_key('delete'): perm_map = {'ticket': perm.TICKET_ADMIN, 'wiki': perm.WIKI_DELETE} self.perm.assert_permission(perm_map[self.attachment_type]) self.env.delete_attachment(self.db, self.attachment_type, self.attachment_id, self.filename) text, link = self.get_attachment_parent_link() self.req.redirect(link) if self.filename and len(self.filename) > 0: # Send an attachment perm_map = {'ticket': perm.TICKET_VIEW, 'wiki': perm.WIKI_VIEW} self.perm.assert_permission(perm_map[self.attachment_type]) self.path = os.path.join(self.env.get_attachments_dir(), self.attachment_type, urllib.quote(self.attachment_id), urllib.quote(self.filename)) try: fd = open(self.path, 'rb') except IOError: raise util.TracError('Attachment not found') stat = os.fstat(fd.fileno()) self.length = stat[6] self.last_modified = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(stat[8])) self.read_func = lambda x, f=fd: f.read(x) self.mime_type = self.env.mimeview.get_mimetype(self.filename) \ or 'application/octet-stream' self.add_link('alternate', self.env.href.attachment(self.attachment_type, self.attachment_id, self.filename, 'txt'), 'Plain Text', 'text/plain') self.add_link('alternate', self.env.href.attachment(self.attachment_type, self.attachment_id, self.filename, 'raw'), 'Original Format', self.mime_type) perm_map = {'ticket': perm.TICKET_ADMIN, 'wiki': perm.WIKI_DELETE} if self.perm.has_permission(perm_map[self.attachment_type]): self.req.hdf.setValue('attachment.delete_href', '?delete=yes') return if self.args.has_key('description') and \ self.args.has_key('author') and \ self.args.has_key('attachment') and \ hasattr(self.args['attachment'], 'file'): if self.args.has_key('cancel'): self.req.redirect(self.get_attachment_parent_link()[1]) # Create a new attachment if not self.attachment_type in ['ticket', 'wiki']: raise util.TracError('Unknown attachment type') perm_map = {'ticket':perm.TICKET_MODIFY, 'wiki': perm.WIKI_MODIFY} self.perm.assert_permission (perm_map[self.attachment_type]) filename = self.env.create_attachment(self.db, self.attachment_type, self.attachment_id, self.args['attachment'], self.args.get('description'), self.args.get('author'), self.req.remote_addr) # Redirect the user to the newly created attachment self.req.redirect(self.env.href.attachment(self.attachment_type, self.attachment_id, filename)) else: # Display an attachment upload form self.view_form = 1