def variable(self, mo): canmiss = False missabort = False key = mo.group(2) # Okay, straightforward must-be-present stuff is # somewhat lacking in features. if key[0] == '?': canmiss = True key = key[1:] elif key[0] == '!': missabort = True key = key[1:] if key and key[0] == '|': key = key[1:] ovars = key.split('|') if not ovars: raise derrors.RendErr("invalid key '%s'" % mo.group(1)) for ov in ovars: if ov in self.context and self.context[ov]: vv = self.context[ov] return httputil.quotehtml(vv) elif not key: raise derrors.RendErr("invalid key '%s'" % mo.group(1)) else: if key in self.context and self.context[key]: return httputil.quotehtml(self.context[key]) # Error if we have to have a value (normal case). if canmiss: return '' elif missabort: raise ReturnNothing("variable expansion empty") raise derrors.RendErr("key with no value: '%s'" % mo.group(1))
def loginbox(context): """Generate the form for a login or logout box. Generates nothing if DWiki authentication is disabled. As a side effect, kills page modification time if it generates anything.""" # If the wiki is not authentication-enabled, you get nothing. if not context.model.has_authentication(): return '' # Login versus non-login makes last-modified unreliable, at # least for pages where we render the login box stuff. context.unrel_time() ppath = context.page.path # Overwriting ppath with :post:page insures that when we are # on virtual pages (perhaps because a login failed) and # we resubmit the form, we go to the right place instead # of a nonexistent virtual page in the normal view, which # would *really* confuse the users. if ":post:page" in context: ppath = context[":post:page"] # NOTE: we do NOT supply the *url* to the page; we supply # the *page*. The difference is crucial if the two are not # the same, because we need the latter. # Are we logged in? # (We have to use url_from_path instead of getting pages, because # we can't *get* these as valid pages. That's the point of the # synthetic names.) qppath = httputil.quotehtml(ppath) if context.current_user() and not context.is_login_default(): turl = context.web.url_from_path(".logout") return logoutBoxForm % (turl, qppath) else: turl = context.web.url_from_path(".login") return loginBoxForm % (turl, qppath)
def commentpre(context): """In a comment-writing context, generate a <pre> block of the comment being written.""" comdata = context.getviewvar("comment") #comdata = comtrim(comdata) if not comdata: return '' return "<pre>\n%s</pre>\n" % httputil.quotehtml(comdata)
def atomcomment(context): """Display the current comment in a way suitable for inclusion in an Atom feed.""" if comments.com_stash_var not in context: return '' c = context[comments.com_stash_var] res = comments.show_comment(c.data, context, wikirend.ABSLINKS) context.newtime(c.time) return httputil.quotehtml(res)
def makelink(text, dest, nofollow = False, ctype = None): if not text: text = '/' nfstr = ''; ctstr = '' if nofollow: nfstr = ' rel="nofollow"' if ctype: ctstr = ' type="%s"' % ctype return '<a%s href="%s"%s>%s</a>' % (ctstr, dest, nfstr, httputil.quotehtml(text))
def commentform(context): """Create the form for writing a new comment in, if the page is commentable by the current user.""" # We are null if we can't comment on the current page. if not context.page.comment_ok(context): return '' comdata = context.getviewvar("comment") whois = context.getviewvar("whois") whourl = context.getviewvar("whourl") if comdata: # We have to do the usual quoting of HTML entities. # The browser stitches up the result and dequotes # them when it gives the whole thing back to us in # POST-production. comdata = httputil.quotehtml(comdata) # We only show the 'post comment' action if there is # some comment text already. if not is_comment_bad(context): post = post_bit else: post = '' else: comdata = '' post = '' curl = context.url(context.page, "writecomment") #previp = remote_ip_prefix(context) # We only generate a valid previp value if the content is good # to start with. if not is_comment_bad(context): previp = gen_ip_prefix(context) else: previp = 'omitted' # TODO: is quotehtml() the right quoting to apply for value="..." # bits? It's not clear to me. I need to read more specifications. data = comment_form % (curl, comdata, httputil.quotehtml(whois), httputil.quotehtml(whourl), previp, post) context.unrel_time() return data
def makelink(text, dest, nofollow=False, ctype=None): if not text: text = '/' nfstr = '' ctstr = '' if nofollow: nfstr = ' rel="nofollow"' if ctype: ctstr = ' type="%s"' % ctype return '<a%s href="%s"%s>%s</a>' % (ctstr, dest, nfstr, httputil.quotehtml(text))
def comauthor(context): """Display the author information for a comment, drawing on the given name, website URL, DWiki login, and comment IP address as necessary and available. Only works inside comment::showall. This potentially generates HTML, not just plain text.""" if com_stash_var not in context: return '' c = context[com_stash_var] ares = [] udata = context.model.get_user(c.user) #uname = c.username if c.username else udata.username if udata else None uname = c.username uurl = c.userurl if c.userurl else \ wikirend.gen_wikilink_url(context, udata.userurl) if udata else None if uname: ares.append("By") ares.append(com_optlink(uname, uurl)) if not c.is_anon(context): ares.append("(%s)" % c.user) elif not c.is_anon(context): ares.append("By") if udata and udata.username: uname = '<abbr title="%s">%s</abbr>' % \ (httputil.quotehtml(udata.username), httputil.quotehtml(c.user)) if uurl: ares.append('<a href="%s">%s</a>' % \ (httputil.quoteurl(uurl), uname)) else: ares.append(uname) else: ares.append(com_optlink(c.user, uurl)) else: ares.append("From") ares.append(com_optlink(c.ip, uurl)) return ' '.join(ares)
def breadcrumbs(context): """Display a 'breadcrumbs' hierarchy of links from the DWiki root to the current page.""" result = [] result.append('<span class="breadcrumbs">') result.append(makelink(context.cfg['wikiname'], context.web.url_from_path(""))) # We don't generate breadcrumbs at the root. # We need to check context.page.path too because we may be # rendering for the root directory in some contexts. if context.page.path != context.wiki_root() and context.page.path: tl = [] curpage = context.page while curpage.path != '': tl.append(curpage) curpage = curpage.parent() tl.reverse() last = tl.pop() skippingPages = False for page in tl: if not page.exists() and skippingPages: continue result.append(" »\n ") if not page.exists(): result.append("....") skippingPages = True continue # Virtual pages breadcrumb in the current view, # because this is what you really want. if page.virtual(): result.append(makelink(page.name, context.url(page))) else: result.append(makelink(page.name, context.nurl(page))) # Last entry is not a link; it's where we *are*. # Making it a link is a) redundant and b) slightly confusing # and c) not how I've done breadcrumbs by hand in the past. # I like my old way, so we do it this way automatically. result.append(" »\n ") result.append(httputil.quotehtml(last.name)) result.append("</span>") return ''.join(result)
def breadcrumbs(context): """Display a 'breadcrumbs' hierarchy of links from the DWiki root to the current page.""" result = [] result.append('<span class="breadcrumbs">') result.append( makelink(context.cfg['wikiname'], context.web.url_from_path(""))) # We don't generate breadcrumbs at the root. # We need to check context.page.path too because we may be # rendering for the root directory in some contexts. if context.page.path != context.wiki_root() and context.page.path: tl = [] curpage = context.page while curpage.path != '': tl.append(curpage) curpage = curpage.parent() tl.reverse() last = tl.pop() skippingPages = False for page in tl: if not page.exists() and skippingPages: continue result.append(" »\n ") if not page.exists(): result.append("....") skippingPages = True continue # Virtual pages breadcrumb in the current view, # because this is what you really want. if page.virtual(): result.append(makelink(page.name, context.url(page))) else: result.append(makelink(page.name, context.nurl(page))) # Last entry is not a link; it's where we *are*. # Making it a link is a) redundant and b) slightly confusing # and c) not how I've done breadcrumbs by hand in the past. # I like my old way, so we do it this way automatically. result.append(" »\n ") result.append(httputil.quotehtml(last.name)) result.append("</span>") return ''.join(result)
def com_optlink(txt, url): if not url: return httputil.quotehtml(txt) return htmlrends.makelink(txt, httputil.quoteurl(url))
def atomcountlink(context): """Just like _comment::countlink_, except that the URL is absolute and the HTML is escaped so that it can be used in an Atom syndication feed.""" return httputil.quotehtml(_gencountlink(context, True))
def titleindex(context): """Like _blog::blog_, except that instead of rendering entries through a template, it just displays a table of dates and entry titles (or relative paths for entries without titles), linking to entries and to the day pages. Respects VirtualDirectory restrictions. Unlike _blog::blog_, it always displays information for all applicable entries.""" if context.page.type != "dir": return '' if not context.page.displayable(): raise derrors.IntErr("undisplayable directory page") # This automatically applies restrictions. dl = context.cache_page_children(context.page) if not dl: return '' # Building a table is unfortunately much more complicated # than a <dl> would be, because we have to use <br> to separate # multiple entries for the same day instead of <td>, which means # that we have to keep track of when we need to generate one and # so on. rl = [ '<table class="blogtitles">\n', ] lday = None dupDict = {} rootpath = context.page.me().path # Rather than directly use a wikirend routine by importing # it, we indirect through the renderer registration. Since # either way we know a wikirend name, I figure this is no # worse. rfunc = htmlrends.get_renderer("wikitext:title:nolinks") for ts, path in dl: # FIXME: this duplication is code smell. np = context.model.get_page(path) if not np.realpage() or np.is_util() or \ not np.access_ok(context): continue pageid = np.identity() if pageid in dupDict: continue else: dupDict[pageid] = None # Do we need to generate a new row for a new day? # Our basic running state is that we are always in # a <td> for page links (except right at the start), # so we must close it off et cetera and then reopen # it. t = time.localtime(ts) plain = "%d-%02d-%02d" % (t.tm_year, t.tm_mon, t.tm_mday) if plain != lday: if lday: # Not first entry ever, so close off # the last day table row. rl.append("\n</td> </tr>\n") rl.append("<tr> <td> %s: </td> <td>\n" % \ link_to_tm(context, t, plain)) lday = plain else: # If we are the second or later entry for a # given day, we must put a <br> between ourselves # and the previous entry. rl.append("<br>\n") # As usual, we must work in a new context. nc = context.clone_to_page(np) ltitle = rfunc(nc) if not ltitle: ltitle = httputil.quotehtml(path[len(rootpath) + 1:]) # We can't use htmlrends.makelink() because that would # quote the live HTML in real titles. rl.append(' <a href="%s">%s</a>' % \ (context.nurl(np), ltitle)) context.newtime(nc.modtime) # Done all; close off the <table> rl.append('\n</td></tr></table>\n') return ''.join(rl)
def titleindex(context): """Like _blog::blog_, except that instead of rendering entries through a template, it just displays a table of dates and entry titles (or relative paths for entries without titles), linking to entries and to the day pages. Respects VirtualDirectory restrictions. Unlike _blog::blog_, it always displays information for all applicable entries.""" if context.page.type != "dir": return '' if not context.page.displayable(): raise derrors.IntErr("undisplayable directory page") # This automatically applies restrictions. dl = context.cache_page_children(context.page) if not dl: return '' # Building a table is unfortunately much more complicated # than a <dl> would be, because we have to use <br> to separate # multiple entries for the same day instead of <td>, which means # that we have to keep track of when we need to generate one and # so on. rl = ['<table class="blogtitles">\n',] lday = None dupDict = {} rootpath = context.page.me().path # Rather than directly use a wikirend routine by importing # it, we indirect through the renderer registration. Since # either way we know a wikirend name, I figure this is no # worse. rfunc = htmlrends.get_renderer("wikitext:title:nolinks") for ts, path in dl: # FIXME: this duplication is code smell. np = context.model.get_page(path) if not np.realpage() or np.is_util() or \ not np.access_ok(context): continue pageid = np.identity() if pageid in dupDict: continue else: dupDict[pageid] = None # Do we need to generate a new row for a new day? # Our basic running state is that we are always in # a <td> for page links (except right at the start), # so we must close it off et cetera and then reopen # it. t = time.localtime(ts) plain = "%d-%02d-%02d" % (t.tm_year, t.tm_mon, t.tm_mday) if plain != lday: if lday: # Not first entry ever, so close off # the last day table row. rl.append("\n</td> </tr>\n") rl.append("<tr> <td> %s: </td> <td>\n" % \ link_to_tm(context, t, plain)) lday = plain else: # If we are the second or later entry for a # given day, we must put a <br> between ourselves # and the previous entry. rl.append("<br>\n") # As usual, we must work in a new context. nc = context.clone_to_page(np) ltitle = rfunc(nc) if not ltitle: ltitle = httputil.quotehtml(path[len(rootpath)+1:]) # We can't use htmlrends.makelink() because that would # quote the live HTML in real titles. rl.append(' <a href="%s">%s</a>' % \ (context.nurl(np), ltitle)) context.newtime(nc.modtime) # Done all; close off the <table> rl.append('\n</td></tr></table>\n') return ''.join(rl)
def genurlent(context, pg, pri): return urlent % (httputil.quotehtml(context.nuri(pg)), pri)
def genviewurlent(context, pg, pri, view): return urlent % (httputil.quotehtml(context.uri(pg, view=view)), pri)
def genviewurlent(context, pg, pri, view): return urlent % (httputil.quotehtml(context.uri(pg, view = view)), pri)
def pagetersenotitle(context): """Generate wikitext:terse:notitle run through a HTML entity quoter, thus suitable for use in Atom feeds.""" return httputil.quotehtml(wikirend.tersenotitle(context))
def feedtitle(context): """Generate an Atom feed title for the current page.""" title = context.getfirst("wikititle", "wikiname") if context.page.path != "": title = title + " :: " + context.page.path return httputil.quotehtml(title)