def _download_link(self, formatter, ns, params, label): if ns == 'download': if formatter.req.perm.has_permission('DOWNLOADS_VIEW'): # Create context. context = Context.from_request(formatter.req)('downloads-wiki') db = self.env.get_db_cnx() context.cursor = db.cursor() # Get API component. api = self.env[DownloadsApi] by_id = False # Get download. if params.strip().isdigit(): download = api.get_download(context, params) by_id = True else: download = api.get_download_by_file(context, params) if download: # Get url part to put after "[project]/downloads/" file_part = download['id'] if by_id else download['file'] if formatter.req.perm.has_permission( 'DOWNLOADS_VIEW', Resource('downloads', download['id'])): # Return link to existing file. return html.a( label, href=formatter.href.downloads(file_part), title='%s (%s)' % (download['file'], pretty_size(download['size']))) else: # File exists but no permission to download it. html.a( label, href='#', title='%s (%s)' % (download['file'], pretty_size(download['size'])), class_='missing') else: # Return link to non-existing file. return html.a(label, href='#', title='File not found.', class_='missing') else: # Return link to file to which is no permission. return html.a(label, href='#', title='No permission to file.', class_='missing')
def expand_macro(self, formatter, name, content): attachment_type = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] db = self.env.get_db_cnx() if db == None: return "No DB connection" attachmentFormattedList="" cursor = db.cursor() if attachment_type == None or attachment_type == "": cursor.execute("SELECT type,id,filename,size,time," "description,author,ipnr FROM attachment") else: cursor.execute("SELECT type,id,filename,size,time," "description,author,ipnr FROM attachment " "WHERE type=%s", (attachment_type, )) formatters={"wiki": formatter.href.wiki, "ticket": formatter.href.ticket} types={"wiki": "", "ticket": "ticket "} return tag.ul( [tag.li( tag.a(filename, href=formatter.href.attachment(type + "/" + id + "/" + filename)), " (", tag.span(pretty_size(size), title=size), ") - added by ", tag.em(author), " to ", tag.a(types[type] + " " + id, href=formatters[type](id)), " ") for type,id,filename,size,time,description,author,ipnr in cursor if self._has_perm(type, id, filename, formatter.context)]) return attachmentFormattedList
def _download_as_zip(self, req, parent, attachments=None): if attachments is None: attachments = self.viewable_attachments(web_context(req, parent)) total_size = sum(attachment.size for attachment in attachments) if total_size > self.max_zip_size: raise TracError( _("Maximum total attachment size: %(num)s", num=pretty_size(self.max_zip_size)), _("Download failed")) req.send_response(200) req.send_header('Content-Type', 'application/zip') filename = 'attachments-%s-%s.zip' % \ (parent.realm, re.sub(r'[/\\:]', '-', unicode(parent.id))) req.send_header('Content-Disposition', content_disposition('inline', filename)) buf = io.BytesIO() with ZipFile(buf, 'w', ZIP_DEFLATED) as zipfile: for attachment in attachments: zipinfo = create_zipinfo(attachment.filename, mtime=attachment.date, comment=attachment.description) try: with attachment.open() as fd: zipfile.writestr(zipinfo, fd.read()) except ResourceNotFound: pass # skip missing files zip_str = buf.getvalue() req.send_header("Content-Length", len(zip_str)) req.end_headers() req.write(zip_str) raise RequestDone()
def attachment_to_hdf(env, req, db, attachment): """ This function have been removed from 0.11, this is copied from 0.10, then modified to work with 0.11 """ if not db: db = env.get_db_cnx() hdf = { 'filename': attachment.filename, 'description': wiki_to_oneliner(attachment.description, env, db, req=req), 'author': attachment.author, 'ipnr': attachment.ipnr, 'size': pretty_size(attachment.size), 'time': format_datetime(attachment.date), 'age': pretty_timedelta(attachment.date), 'href': AttachmentModule(env).get_resource_url(attachment.resource, req.href) } return hdf
def expand_macro(self, formatter, name, content): args, kw = parse_args(content) page = kw.get('page', '') sort = kw.get('sort', 'DESC') order = kw.get('order', 'time') self.env.log.error('sort %s, order %s' % (sort, order)) attachment_type = "" wiki_path = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] db = self.env.get_db_cnx() if db == None: return "No DB connection" attachmentFormattedList = "" cursor = db.cursor() if attachment_type == None or attachment_type == "": cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment") elif page == None or page == "": cursor.execute( "SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment WHERE type=%s ORDER " "BY " + order + " " + sort, (attachment_type, )) else: cursor.execute( "SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment WHERE type=%s and " "id=%s ORDER BY " + order + " " + sort, (attachment_type, page)) formatters = { "wiki": formatter.href.wiki, "ticket": formatter.href.ticket } types = {"wiki": "", "ticket": "ticket "} return tag.ul([ tag.li( tag.a(filename, href=formatter.href.attachment(type + "/" + id + "/" + filename)), " (", tag.span(pretty_size(size), title=size), ") - ", tag.em(format_datetime(time)), " - added by ", tag.em(author), " to ", tag.a(types[type] + " " + id, href=formatters[type](id)), " ") for type, id, filename, size, time, description, author, ipnr in cursor ]) return attachmentFormattedList
def _do_list(self, resource): realm, id_ = self.split_resource(resource) print_table([(a.filename, pretty_size(a.size), a.author, format_datetime(a.date, console_datetime_format), a.description) for a in Attachment.select(self.env, realm, id_)], [_("Name"), _("Size"), _("Author"), _("Date"), _("Description")])
def _do_list(self, resource): (realm, id) = self.split_resource(resource) print_table([(a.filename, pretty_size(a.size), a.author, format_datetime(a.date, console_datetime_format), a.description) for a in Attachment.select(self.env, realm, id)], [_('Name'), _('Size'), _('Author'), _('Date'), _('Description')])
def _render_directory(self, req, repos, node, rev=None): req.perm.assert_permission('BROWSER_VIEW') # Entries metadata info = [] for entry in node.get_entries(): info.append({ 'name': entry.name, 'fullpath': entry.path, 'is_dir': entry.isdir, 'content_length': entry.content_length, 'size': pretty_size(entry.content_length), 'rev': entry.rev, 'log_href': req.href.log(entry.path, rev=rev), 'browser_href': req.href.browser(entry.path, rev=rev) }) changes = get_changes(self.env, repos, [i['rev'] for i in info]) # Ordering of entries order = req.args.get('order', 'name').lower() desc = req.args.has_key('desc') if order == 'date': def file_order(a): return changes[a['rev']]['date_seconds'] elif order == 'size': def file_order(a): return (a['content_length'], embedded_numbers(a['name'].lower())) else: def file_order(a): return embedded_numbers(a['name'].lower()) dir_order = desc and 1 or -1 def browse_order(a): return a['is_dir'] and dir_order or 0, file_order(a) info = sorted(info, key=browse_order, reverse=desc) switch_ordering_hrefs = {} for col in ('name', 'size', 'date'): switch_ordering_hrefs[col] = req.href.browser( node.path, rev=rev, order=col, desc=(col == order and not desc and 1 or None)) # ''Zip Archive'' alternate link patterns = self.downloadable_paths if node.path and patterns and \ filter(None, [fnmatchcase(node.path, p) for p in patterns]): zip_href = req.href.changeset(rev or repos.youngest_rev, node.path, old=rev, old_path='/', format='zip') add_link(req, 'alternate', zip_href, 'Zip Archive', 'application/zip', 'zip') req.hdf['browser'] = {'order': order, 'desc': desc and 1 or 0, 'items': info, 'changes': changes, 'order_href': switch_ordering_hrefs}
def _download_link(self, formatter, ns, params, label): if ns == 'download': if formatter.req.perm.has_permission('DOWNLOADS_VIEW'): # Create context. context = Context.from_request(formatter.req)('downloads-wiki') db = self.env.get_db_cnx() context.cursor = db.cursor() # Get API component. api = self.env[DownloadsApi] by_id = False # Get download. if params.strip().isdigit(): download = api.get_download(context, params) by_id = True else: download = api.get_download_by_file(context, params) if download: # Get url part to put after "[project]/downloads/" file_part = download['id'] if by_id else download['file'] if formatter.req.perm.has_permission('DOWNLOADS_VIEW', Resource('downloads', download['id'])): # Return link to existing file. return html.a(label, href = formatter.href.downloads( file_part), title = '%s (%s)' % (download['file'], pretty_size(download['size']))) else: # File exists but no permission to download it. html.a(label, href = '#', title = '%s (%s)' % ( download['file'], pretty_size(download['size'])), class_ = 'missing') else: # Return link to non-existing file. return html.a(label, href = '#', title = 'File not found.', class_ = 'missing') else: # Return link to file to which is no permission. return html.a(label, href = '#', title = 'No permission to file.', class_ = 'missing')
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description, size = event[3] # Return apropriate content. if field == 'url': return context.req.href.downloads(id) elif field == 'title': return tag('New download ', tag.em(name), ' created') elif field == 'description': return tag('(%s) ' % (pretty_size(size),), format_to_oneliner( self.env, context, description))
def render_timeline_event(self, context, field, event): # Decompose event data. id, name, description, size = event[3] # Return apropriate content. if field == 'url': return context.req.href.downloads(id) elif field == 'title': return tag('New download ', tag.em(name), ' created') elif field == 'description': return tag('(%s) ' % (pretty_size(size), ), format_to_oneliner(self.env, context, description))
def _download_link(self, formatter, ns, params, label): if ns == 'download': if 'DOWNLOADS_VIEW' in formatter.req.perm: api = self.env[DownloadsApi] # Get download. if re.match(r'\d+', params): download = api.get_download(params) else: download = api.get_download_by_file(params) if download: resource = Resource('downloads', download['id']) if 'DOWNLOADS_VIEW' in formatter.req.perm(resource): # Return link to existing file. return html.a( label, href=formatter.href.downloads(params), title='%s (%s)' % (download['file'], pretty_size(download['size']))) else: # File exists but no permission to download it. html.a( label, href='#', title='%s (%s)' % (download['file'], pretty_size(download['size'])), class_='missing') else: # Return link to non-existing file. return html.a(label, href='#', title='File not found.', class_='missing') else: # Return link to file to which is no permission. return html.a(label, href='#', title='No permission to file.', class_='missing')
def expand_macro(self, formatter, name, content): args, kw = parse_args(content) page = kw.get('page', '') sort = kw.get('sort', 'DESC') order = kw.get('order', 'time') self.env.log.error('sort %s, order %s' % (sort, order)) attachment_type = "" wiki_path = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] db = self.env.get_db_cnx() if db == None: return "No DB connection" attachmentFormattedList="" cursor = db.cursor() if attachment_type == None or attachment_type == "": cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment") elif page == None or page == "": cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment WHERE type=%s ORDER " "BY " + order + " " + sort, (attachment_type,)) else: cursor.execute("SELECT type,id,filename,size,time,description," "author,ipnr FROM attachment WHERE type=%s and " "id=%s ORDER BY " + order + " " + sort, (attachment_type, page)) formatters={"wiki": formatter.href.wiki, "ticket": formatter.href.ticket} types={"wiki": "", "ticket": "ticket "} return tag.ul( [tag.li( tag.a(filename, href=formatter.href.attachment(type + "/" + id + "/" + filename)), " (", tag.span(pretty_size(size), title=size), ") - ", tag.em(format_datetime(time)), " - added by ", tag.em(author), " to ", tag.a(types[type] + " " + id, href=formatters[type](id)), " ") for type,id,filename,size,time,description,author,ipnr in cursor]) return attachmentFormattedList
def attachment_to_hdf(env, req, db, attachment): if not db: db = env.get_db_cnx() hdf = { 'filename': attachment.filename, 'description': wiki_to_oneliner(attachment.description, env, db), 'author': attachment.author, 'ipnr': attachment.ipnr, 'size': pretty_size(attachment.size), 'time': format_datetime(attachment.time), 'age': pretty_timedelta(attachment.time), 'href': attachment.href(req) } return hdf
def _download_as_zip(self, req, parent, attachments=None): if attachments is None: attachments = self.viewable_attachments(web_context(req, parent)) total_size = sum(attachment.size for attachment in attachments) if total_size > self.max_zip_size: raise TracError( _("Maximum total attachment size: %(num)s", num=pretty_size(self.max_zip_size)), _("Download failed")) req.send_response(200) req.send_header('Content-Type', 'application/zip') filename = 'attachments-%s-%s.zip' % \ (parent.realm, re.sub(r'[/\\:]', '-', unicode(parent.id))) req.send_header('Content-Disposition', content_disposition('inline', filename)) 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 fileobj = TemporaryFile(prefix='trac-', suffix='.zip') try: zipfile = ZipFile(fileobj, 'w', ZIP_DEFLATED) for attachment in attachments: zipinfo = create_zipinfo(attachment.filename, mtime=attachment.date, comment=attachment.description) try: with attachment.open() as fd: zipfile.writestr(zipinfo, fd.read()) except ResourceNotFound: pass # skip missing files else: pos = write_partial(fileobj, pos) finally: try: zipfile.close() write_partial(fileobj, pos) finally: fileobj.close() raise RequestDone
def get_resource_description(self, resource, format='default', context=None, **kwargs): api = self.env[DownloadsApi] download = api.get_download(resource.id) if format == 'compact': return download['file'] elif format == 'summary': return '(%s) %s' % (pretty_size( download['size']), download['description']) return download['file']
def get_resource_description(self, resource, format="default", context=None, **kwargs): # Create context. context = Context("downloads-core") db = self.env.get_db_cnx() context.cursor = db.cursor() # Get download from ID. api = self.env[DownloadsApi] download = api.get_download(context, safe_int(resource.id)) if format == "compact": return download["file"] elif format == "summary": return "(%s) %s" % (pretty_size(download["size"]), download["description"]) return download["file"]
def _do_list(self): # Get downloads API component. api = self.env[DownloadsApi] # Create context. context = Context('downloads-consoleadmin') db = self.env.get_db_cnx() context.cursor = db.cursor() # Print uploded download downloads = api.get_downloads(context) print_table([(download['id'], download['file'], pretty_size( download['size']), format_datetime(download['time']), download['component'], download['version'], download['platform']['name'], download['type']['name']) for download in downloads], ['ID', 'Filename', 'Size', 'Uploaded', 'Component', 'Version', 'Platform', 'Type'])
def get_resource_description(self, resource, format = 'default', context = None, **kwargs): # Create context. context = Context('downloads-core') db = self.env.get_db_cnx() context.cursor = db.cursor() # Get download from ID. api = self.env[DownloadsApi] download = api.get_download(context, resource.id) if format == 'compact': return download['file'] elif format == 'summary': return '(%s) %s' % (pretty_size(download['size']), download['description']) return download['file']
def expand_macro(self, formatter, name, content): attachment_type = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] with self.env.db_transaction as db: if attachment_type is None or attachment_type == "": attachments = db(""" SELECT type,id,filename,size,time, description,author,ipnr FROM attachment """) else: attachments = db( """ SELECT type,id,filename,size,time, description,author,ipnr FROM attachment WHERE type=%s """, (attachment_type, )) formatters = { 'wiki': formatter.href.wiki, 'ticket': formatter.href.ticket, 'milestone': formatter.href.milestone, } types = { 'wiki': '', 'ticket': 'ticket ', 'milestone': 'milestone ', } return html.ul([ html.li( html.a(filename, href=formatter.href.attachment(type + '/' + id + '/' + filename)), " (", html.span(pretty_size(size), title=size), ") - added by ", html.em(author), " to ", html.a(types[type] + ' ' + id, href=formatters[type](id)), ' ') for type, id, filename, size, time, description, author, ipnr in attachments if self._has_perm(type, id, filename, formatter.context) ])
def expand_macro(self, formatter, name, content): attachment_type = "" if content: argv = [arg.strip() for arg in content.split(',')] if len(argv) > 0: attachment_type = argv[0] with self.env.db_transaction as db: if attachment_type is None or attachment_type == "": attachments = db(""" SELECT type,id,filename,size,time, description,author,ipnr FROM attachment """) else: attachments = db(""" SELECT type,id,filename,size,time, description,author,ipnr FROM attachment WHERE type=%s """, (attachment_type, )) formatters = { 'wiki': formatter.href.wiki, 'ticket': formatter.href.ticket, 'milestone': formatter.href.milestone, } types = { 'wiki': '', 'ticket': 'ticket ', 'milestone': 'milestone ', } return html.ul( [html.li( html.a(filename, href=formatter.href.attachment(type + '/' + id + '/' + filename)), " (", html.span(pretty_size(size), title=size), ") - added by ", html.em(author), " to ", html.a(types[type] + ' ' + id, href=formatters[type](id)), ' ') for type, id, filename, size, time, description, author, ipnr in attachments if self._has_perm(type, id, filename, formatter.context)])
def _do_list(self): # Get downloads API component. api = self.env[DownloadsApi] # Create context. context = Context('downloads-consoleadmin') db = self.env.get_db_cnx() context.cursor = db.cursor() # Print uploded download downloads = api.get_downloads(context) print_table( [(download['id'], download['file'], pretty_size(download['size']), format_datetime(download['time']), download['component'], download['version'], download['architecture']['name'], download['platform']['name'], download['type']['name']) for download in downloads], [ 'ID', 'Filename', 'Size', 'Uploaded', 'Component', 'Version', 'Architecture', 'Platform', 'Type' ])
def get_resource_description(self, resource, format='default', context=None, **kwargs): # Create context. context = Context('downloads-core') db = self.env.get_db_cnx() context.cursor = db.cursor() # Get download from ID. api = self.env[DownloadsApi] download = api.get_download(context, safe_int(resource.id)) if format == 'compact': return download['file'] elif format == 'summary': return '(%s) %s' % (pretty_size( download['size']), download['description']) return download['file']
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')
def _do_save(self, req, attachment): req.perm(attachment.resource).require('ATTACHMENT_CREATE') parent_resource = attachment.resource.parent if 'cancel' in req.args: req.redirect(get_resource_url(self.env, parent_resource, req.href)) upload = req.args.getfirst('attachment') if not hasattr(upload, 'filename') or not upload.filename: raise TracError(_("No file uploaded")) if hasattr(upload.file, 'fileno'): size = os.fstat(upload.file.fileno())[6] else: upload.file.seek(0, 2) # seek to end of file size = upload.file.tell() upload.file.seek(0) if size == 0: raise TracError(_("Can't upload empty file")) # Maximum attachment size (in bytes) max_size = self.max_size if 0 <= max_size < size: raise TracError( _("Maximum attachment size: %(num)s", num=pretty_size(max_size)), _("Upload failed")) filename = _normalized_filename(upload.filename) if not filename: raise TracError(_("No file uploaded")) # Now the filename is known, update the attachment resource attachment.filename = filename attachment.description = req.args.get('description', '') attachment.author = get_reporter_id(req, 'author') attachment.ipnr = req.remote_addr # Validate attachment valid = True for manipulator in self.manipulators: for field, message in manipulator.validate_attachment( req, attachment): valid = False if field: add_warning( req, tag_( "Attachment field %(field)s is invalid: " "%(message)s", field=tag.strong(field), message=message)) else: add_warning( req, tag_("Invalid attachment: %(message)s", message=message)) if not valid: # Display the attach form with pre-existing data # NOTE: Local file path not known, file field cannot be repopulated add_warning(req, _('Note: File must be selected again.')) data = self._render_form(req, attachment) data['is_replace'] = req.args.get('replace') return data if req.args.get('replace'): try: old_attachment = Attachment(self.env, attachment.resource(id=filename)) if not (req.authname and req.authname != 'anonymous' and old_attachment.author == req.authname) \ and 'ATTACHMENT_DELETE' \ not in req.perm(attachment.resource): raise PermissionError(msg=_( "You don't have permission to " "replace the attachment %(name)s. You can only " "replace your own attachments. Replacing other's " "attachments requires ATTACHMENT_DELETE permission.", name=filename)) if (not attachment.description.strip() and old_attachment.description): attachment.description = old_attachment.description old_attachment.delete() except TracError: pass # don't worry if there's nothing to replace attachment.insert(filename, upload.file, size) req.redirect( get_resource_url(self.env, attachment.resource(id=None), req.href))
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')
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')
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')
def _do_save(self, req, attachment): req.perm(attachment.resource).require('ATTACHMENT_CREATE') parent_resource = attachment.resource.parent if 'cancel' in req.args: req.redirect(get_resource_url(self.env, parent_resource, req.href)) filename, fileobj, filesize = req.args.getfile('attachment') if not filename: raise TracError(_("No file uploaded")) upload_failed = _("Upload failed for %(filename)s", filename=filename) if filesize == 0: raise TracError(_("Can't upload empty file"), upload_failed) if 0 <= self.max_size < filesize: raise TracError( _("Maximum attachment size: %(num)s", num=pretty_size(self.max_size)), upload_failed) # Now the filename is known, update the attachment resource attachment.filename = filename attachment.description = req.args.get('description', '') attachment.author = get_reporter_id(req, 'author') # Validate attachment valid = True for manipulator in self.manipulators: for field, message in manipulator.validate_attachment( req, attachment): valid = False if field: add_warning( req, tag_( "Attachment field %(field)s is invalid: " "%(message)s", field=tag.strong(field), message=message)) else: add_warning( req, tag_("Invalid attachment: %(message)s", message=message)) if not valid: # Display the attach form with pre-existing data # NOTE: Local file path not known, file field cannot be repopulated add_warning(req, _("Note: File must be selected again.")) data = self._render_form(req, attachment) data['is_replace'] = req.args.get('replace') return data if req.args.get('replace'): try: old_attachment = Attachment(self.env, attachment.resource(id=filename)) req.perm(attachment.resource).require( 'ATTACHMENT_DELETE', message=_( "You don't have permission to replace the " "attachment %(name)s. You can only replace " "your own attachments. Replacing other's " "attachments requires ATTACHMENT_DELETE " "permission.", name=filename)) if (not attachment.description.strip() and old_attachment.description): attachment.description = old_attachment.description old_attachment.delete() except TracError: pass # don't worry if there's nothing to replace attachment.insert(filename, fileobj, filesize) req.redirect( get_resource_url(self.env, attachment.resource(id=None), req.href))