include werc
This commit is contained in:
parent
58fe4bd42c
commit
217f8d61a1
73 changed files with 5835 additions and 0 deletions
79
werc/README
Normal file
79
werc/README
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
werc - a minimalist document management system
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
Werc is a content management system and web (anti-)framework designed to be simple to
|
||||||
|
use, simple to setup, simple to hack on, and not get in the way while allowing
|
||||||
|
users easy customization.
|
||||||
|
|
||||||
|
For more information see the official website: http://werc.cat-v.org/
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
* An http server that can handle CGIs
|
||||||
|
* Plan 9 from User Space: http://swtch.com/plan9port,
|
||||||
|
Or 9base-tip: http://tools.suckless.org/9base,
|
||||||
|
Or frontbase: http://openbsd.stanleylieber.com/frontbase
|
||||||
|
|
||||||
|
Note: Werc by default expects the Plan 9 tools to be installed under
|
||||||
|
/bin/, if you have installed them elsewhere you will need to edit the
|
||||||
|
#! line in bin/werc.rc and customize the $plan9port variable in your
|
||||||
|
etc/initrc.local.
|
||||||
|
|
||||||
|
|
||||||
|
Instructions:
|
||||||
|
|
||||||
|
Untar werc at your desired location, configure httpd to use
|
||||||
|
/path-to-your-werc-installation/bin/werc.rc as a cgi-script, it is recommended
|
||||||
|
that you make werc.rc handle all non-static files (this can be done by setting
|
||||||
|
it up as your 404 handler) and setup your virtual hosts to handle static files
|
||||||
|
by setting the document root for the domain to
|
||||||
|
/path-to-werc-installation/sites/yourdomain.com/, and create a directory for
|
||||||
|
your web site under sites/ where you can start adding content right away.
|
||||||
|
|
||||||
|
If you will want to allow updates via the web interface (eg., for wiki or
|
||||||
|
comments apps) make sure all files under sites/ are writable by the user your
|
||||||
|
cgi will run as, usually www-data, for example by doing: chown -R :www-data
|
||||||
|
sites/; chmod -R g+w sites/
|
||||||
|
|
||||||
|
If your Plan 9 binaries are located somewhere else than the standard /bin/ you
|
||||||
|
will need to edit the first line of bin/werc.rc (Note that p9p in particular is
|
||||||
|
picky about where it is located, once you run ./INSTALL you should *not* move
|
||||||
|
it to a different directory without running ./INSTALL again.)
|
||||||
|
|
||||||
|
For general configuration options copy etc/initrc to etc/initrc.local and
|
||||||
|
customize it as needed. Site (and directory) specific options can be set in a
|
||||||
|
sites/example.com/_werc/config file inside the site's directory. To customize
|
||||||
|
templates and included files you can store your own version of the files in
|
||||||
|
lib/ under sites/example.com/_werc/lib.
|
||||||
|
|
||||||
|
The source tree for the werc website is included under sites/werc.cat-v.org as
|
||||||
|
an example, feel free to use it as a template for your own site.
|
||||||
|
|
||||||
|
For more details see the documentation section of the website:
|
||||||
|
http://werc.cat-v.org/docs/
|
||||||
|
|
||||||
|
|
||||||
|
Contact
|
||||||
|
-------
|
||||||
|
|
||||||
|
For comments, suggestions, bug reports or patches join the werc mailing list
|
||||||
|
at: http://werc.cat-v.org or the irc channel #cat-v in irc.freenode.org
|
||||||
|
|
||||||
|
If you have a public website that uses werc I would love to hear about it and
|
||||||
|
get feedback about you experience setting it up.
|
||||||
|
|
||||||
|
Thanks
|
||||||
|
------
|
||||||
|
|
||||||
|
Garbeam, Kris Maglione, sqweek, soul9, mycroftiv, maht, yiyus, cinap_lenrek,
|
||||||
|
khm and many others for their ideas, patches, testing and other contributions.
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Werc is in the public domain.
|
142
werc/apps/blagh/app.rc
Normal file
142
werc/apps/blagh/app.rc
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
fn conf_enable_blog {
|
||||||
|
blagh_uri=$conf_wd
|
||||||
|
blagh_dirs=$*
|
||||||
|
if(~ $#blagh_dirs 0)
|
||||||
|
blagh_dirs=( . )
|
||||||
|
conf_enable_app blagh
|
||||||
|
|
||||||
|
if(~ $"conf_blog_editors '')
|
||||||
|
conf_blog_editors=blog-editors
|
||||||
|
|
||||||
|
if(~ $"conf_max_posts_per_page '')
|
||||||
|
conf_max_posts_per_page=32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blagh_init {
|
||||||
|
if(~ $#blagh_dirs 0 && ~ $req_path */[bB]log/*) {
|
||||||
|
blagh_uri=`{echo $req_path | sed 's,(/[bB]log/).*,\1,'}
|
||||||
|
blagh_dirs=( . )
|
||||||
|
}
|
||||||
|
|
||||||
|
# Should not match sub-dirs!
|
||||||
|
if(! ~ $#blagh_dirs 0) {
|
||||||
|
# && test -d / `{echo '-a -d '^$blagh_root^$blagh_dirs}
|
||||||
|
blagh_url=$base_url^$blagh_uri
|
||||||
|
blagh_root=$sitedir^$blagh_uri
|
||||||
|
if(check_user $conf_blog_editors) {
|
||||||
|
editor_mode=on
|
||||||
|
if(~ $"post_arg_date '')
|
||||||
|
post_date=`{datei|sed 's,-,/,g'}
|
||||||
|
if not
|
||||||
|
post_date=$post_arg_date
|
||||||
|
ll_add handlers_bar_left echo '<a href="'$blagh_uri'new_post">Make a new post</a>'
|
||||||
|
}
|
||||||
|
|
||||||
|
if(~ $req_path $blagh_uri) {
|
||||||
|
handler_body_main=blagh_body
|
||||||
|
u=$blagh_uri'index'
|
||||||
|
extraHeaders=$"extraHeaders ^ \
|
||||||
|
'<link rel="alternate" type="application/atom+xml" title="ATOM" href="'$"u'.atom" />
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="'$"u'.rss" />
|
||||||
|
<link rel="alternate" type="application/json" title="JSON" href="'$"blagh_uri'feed.json" />'
|
||||||
|
}
|
||||||
|
if not if(~ $req_path $blagh_uri^index.atom)
|
||||||
|
blagh_setup_feed_handlers atom.tpl 'application/atom+xml'
|
||||||
|
|
||||||
|
if not if(~ $req_path $blagh_uri^index.rss)
|
||||||
|
blagh_setup_feed_handlers rss20.tpl 'text/xml; charset=utf-8'
|
||||||
|
|
||||||
|
if not if(~ $req_path $blagh_uri^feed.json)
|
||||||
|
blagh_setup_feed_handlers jsonfeed.tpl 'application/json; charset=utf-8'
|
||||||
|
|
||||||
|
if not if(~ $req_path $blagh_uri^new_post && ! ~ $#editor_mode 0) {
|
||||||
|
handler_body_main=( tpl_handler `{get_lib_file blagh/new_post.tpl apps/blagh/new_post.tpl} )
|
||||||
|
if(~ $REQUEST_METHOD POST) {
|
||||||
|
if(mkbpost $"post_arg_body $"post_date $"post_arg_title $post_arg_id)
|
||||||
|
post_redirect $blagh_uri
|
||||||
|
if not
|
||||||
|
notify_errors=$status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blagh_setup_feed_handlers {
|
||||||
|
handler_body_main=NOT_USED_by_blagh_feeds
|
||||||
|
res_tail=()
|
||||||
|
http_content_type=$2
|
||||||
|
headers=()
|
||||||
|
master_template=apps/blagh/$1 # Should we allow tempalte override?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blagh_body {
|
||||||
|
if (! ~ $"blogTitle '')
|
||||||
|
echo '<h1>'$"blogTitle'</h1>'
|
||||||
|
|
||||||
|
# Direct links to feeds are disabled because they are not very useful, add clutter and might waste pagerank.
|
||||||
|
# An user can add this on their own using handlers_body_head anyway.
|
||||||
|
#echo '<div style="text-align:right">(<a href="index.rss">RSS Feed</a>|<a href="index.atom">Atom Feed</a>)</div>'
|
||||||
|
|
||||||
|
# XXX Not sure why this fixes issues with blog setup, probably bug in fltr_cache!
|
||||||
|
for(p in `{get_post_list $blagh_root^$blagh_dirs}) {
|
||||||
|
l=`{echo -n $p|sed 's!'$sitedir^'/?(.*)([0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9])(/[^/]+/)!\2 /\1\2\3!'}
|
||||||
|
sed '1s!.*![&]('^$l(2)^') ('^$l(1)^')!' < $p/index.md
|
||||||
|
echo # Needed extra \n so markdown doesn't mess up the formatting, probably can be done in sed.
|
||||||
|
} | $formatter
|
||||||
|
# XXX BUG! Markdown [references] break because multiple markdown documents are merged. Should format each blog post independently.
|
||||||
|
# TODO: use fltr_cache directly, that can fix the previous bug plus provide a perf boost by caching title generation.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_post_list {
|
||||||
|
# /./->/|/ done to sort -t| and order by date
|
||||||
|
# Note: $paths in blagh_dirs should not contain '/./' or '|'
|
||||||
|
ls -F $*^/./[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]/ >[2]/dev/null | sed -n '/'^$forbidden_uri_chars^'/d; s,/\./,/|/,; /\/$/p' | sort -r '-t|' +1 | sed -e 's,/+\|/+,/,' -e $conf_max_posts_per_page^'q'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mkbpost {
|
||||||
|
bptext=$1
|
||||||
|
bpdate=$2
|
||||||
|
bptitle=$3
|
||||||
|
bpid=$4
|
||||||
|
_status=()
|
||||||
|
if(~ $"bptext '')
|
||||||
|
_status=($_status 'You need to provide a post body.')
|
||||||
|
if(! ~ $"bpdate [0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9])
|
||||||
|
_status=($_status 'Invalid date: '''^$"bpdate^'''') # XXX Should make semantic check.
|
||||||
|
|
||||||
|
if(~ $#_status 0) {
|
||||||
|
umask 002 # Let group write
|
||||||
|
if(! ~ $"bpid '')
|
||||||
|
bpid=`{echo -n '-'^$bpid | sed 's/'$forbidden_uri_chars'+/_/g; 1q'}
|
||||||
|
|
||||||
|
ddir=$blagh_root^$bpdate^'/'
|
||||||
|
n=`{ls $ddir >[2]/dev/null |wc -l}
|
||||||
|
|
||||||
|
mkdir -p $ddir/$"n^$"bpid/
|
||||||
|
{
|
||||||
|
if(! ~ $"bptitle '') {
|
||||||
|
echo $bptitle
|
||||||
|
echo '========================================='
|
||||||
|
}
|
||||||
|
# TODO: Enable metadata
|
||||||
|
#echo '* Posted:' `{date}
|
||||||
|
#if(! ~ $#logged_user 0)
|
||||||
|
# echo '* Author: '$logged_user
|
||||||
|
echo
|
||||||
|
echo $bptext
|
||||||
|
}> $ddir/$"n^$"bpid/index.md
|
||||||
|
|
||||||
|
# Experimental support for http://pubsubhubbub.googlecode.com/
|
||||||
|
if(! ~ $"conf_blog_pubsubdub_hub '') {
|
||||||
|
ifs='' { p=`{echo $req_url|sed 's/new_post$/index.atom/'|url_encode } }
|
||||||
|
dprint hget -p 'hub.mode=publish&hub.url='^$"p $conf_blog_pubsubdub_hub
|
||||||
|
hget -d -h -p 'hub.mode=publish&hub.url='^$"p $conf_blog_pubsubdub_hub >[1=2] &
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status=$_status
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strip_title_from_md_file {
|
||||||
|
sed '1N; /^.*\n===*$/N; /.*\n===*\n$/d'
|
||||||
|
}
|
58
werc/apps/blagh/atom.tpl
Normal file
58
werc/apps/blagh/atom.tpl
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
%{
|
||||||
|
# See for more info:http://www.tbray.org/ongoing/When/200x/2005/07/27/Atomic-RSS
|
||||||
|
fn statpost {
|
||||||
|
f = $1
|
||||||
|
|
||||||
|
post_uri=$base_url^`{cleanname `{echo $f | sed -e 's!^'$sitedir'!!'}}^'/'
|
||||||
|
title=`{read $f/index.md}
|
||||||
|
by=`{ls -m $f | sed 's/^\[//g; s/].*$//g' >[2]/dev/null}
|
||||||
|
ifs=() { summary=`{cat $f/index.md | strip_title_from_md_file | ifs=$difs {$formatter} } }
|
||||||
|
}
|
||||||
|
# rfc3339 date when feed was last updated.
|
||||||
|
fupdated = `{ndate -a `{date `{mtime `{ls $blagh_root$blagh_dirs/[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]/[0-9] | tail -1} | awk '{print $1}'}}}
|
||||||
|
%}
|
||||||
|
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||||
|
xmlns:thr="http://purl.org/syndication/thread/1.0">
|
||||||
|
|
||||||
|
% if(! ~ $"conf_blog_pubsubdub_hub '') {
|
||||||
|
% echo '<link rel="hub" href="'$conf_blog_pubsubdub_hub'" />'
|
||||||
|
% }
|
||||||
|
|
||||||
|
<link rel="self" href="%($base_url^$req_path%)"/>
|
||||||
|
<id>%($base_url^$req_path%)</id>
|
||||||
|
<icon><![CDATA[/favicon.ico]]></icon>
|
||||||
|
|
||||||
|
<title><![CDATA[%($siteTitle%)]]></title>
|
||||||
|
<subtitle><![CDATA[%($siteSubTitle%)]]></subtitle>
|
||||||
|
|
||||||
|
<updated>%($fupdated%)</updated>
|
||||||
|
<link href="."/>
|
||||||
|
|
||||||
|
% for(f in `{get_post_list $blagh_root$blagh_dirs}) {
|
||||||
|
% statpost $f
|
||||||
|
|
||||||
|
<entry>
|
||||||
|
% # Maybe we should be smarter, see: http://diveintomark.org/archives/2004/05/28/howto-atom-id, example: <id>tag:intertwingly.net,2004:2899</id>
|
||||||
|
<id>%($post_uri%)</id>
|
||||||
|
<link href="%($post_uri%)"/>
|
||||||
|
<title><![CDATA[%($title%)]]></title>
|
||||||
|
% # <link rel="replies" href="2899.atom" thr:count="0"/>
|
||||||
|
<author><name><![CDATA[%($by%)]]></name></author>
|
||||||
|
|
||||||
|
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<![CDATA[%($summary%)]]>
|
||||||
|
</div></content>
|
||||||
|
|
||||||
|
% # rfc3339 date when entry was last updated.
|
||||||
|
% eupdated=`{ndate -a `{date `{mtime $f | awk '{print $1}'}}}
|
||||||
|
<updated>%($eupdated%)</updated>
|
||||||
|
</entry>
|
||||||
|
|
||||||
|
% }
|
||||||
|
|
||||||
|
</feed>
|
||||||
|
|
||||||
|
% exit
|
20
werc/apps/blagh/convert.rc
Executable file
20
werc/apps/blagh/convert.rc
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env rc
|
||||||
|
|
||||||
|
path=($PLAN9/bin/ $path)
|
||||||
|
|
||||||
|
for(p in *.md) {
|
||||||
|
echo
|
||||||
|
echo '========================='
|
||||||
|
echo p $p
|
||||||
|
pp=`{echo $p | sed 's/^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])[\-_](.*).md$/\1 \2 \3 \4/' }
|
||||||
|
echo pp $pp
|
||||||
|
|
||||||
|
d=$pp(1)^'/'^$pp(2)^'/'^$pp(3)^'/'^$pp(4)^'/'
|
||||||
|
|
||||||
|
mkdir -p $d
|
||||||
|
echo $pp(4) | sed -e 's/^[0-9]_//; s/_/ /g;' > $d/index.md
|
||||||
|
echo '=================================' >> $d/index.md
|
||||||
|
echo >> $d/index.md
|
||||||
|
cat $p >> $d/index.md
|
||||||
|
|
||||||
|
}
|
35
werc/apps/blagh/jsonfeed.tpl
Normal file
35
werc/apps/blagh/jsonfeed.tpl
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"version": "https://jsonfeed.org/version/1",
|
||||||
|
"title": "%($siteTitle%)",
|
||||||
|
"home_page_url": "%($"base_url%)",
|
||||||
|
"feed_url": "%($"base_url^$"req_path%)",
|
||||||
|
"items": [
|
||||||
|
%{
|
||||||
|
fn statpost {
|
||||||
|
f = $1
|
||||||
|
post_uri=$base_url^`{cleanname `{echo $f | sed -e 's!^'$sitedir'!!'}}^'/'
|
||||||
|
title=`{read $f/index.md}
|
||||||
|
#ifs=() { summary=`{cat $f/index.md | crop_text 1024 ... | $formatter } }
|
||||||
|
ifs=() { summary=`{cat $f/index.md | strip_title_from_md_file | ifs=$difs {$formatter| sed 's/"/\\"/g' | tr -d '\012' } } }
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
% #for(f in `{get_post_list $blagh_root$blagh_dirs}) {
|
||||||
|
%
|
||||||
|
% postlist=`{get_post_list $blagh_root$blagh_dirs}
|
||||||
|
% postcount=0
|
||||||
|
% for(f in $postlist) {
|
||||||
|
% statpost $f
|
||||||
|
{
|
||||||
|
"id": "%($post_uri%)",
|
||||||
|
"url": "%($post_uri%)",
|
||||||
|
"title": "%($title%)",
|
||||||
|
"content_html": "%($summary%)"
|
||||||
|
}
|
||||||
|
% postcount = `{echo $postcount 1+p | dc}
|
||||||
|
% if (! ~ $#postlist $postcount) { echo , }
|
||||||
|
% }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
% exit
|
||||||
|
|
11
werc/apps/blagh/new_post.tpl
Normal file
11
werc/apps/blagh/new_post.tpl
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<div>
|
||||||
|
% notices_handler
|
||||||
|
<form method="POST"><fieldset>
|
||||||
|
<legend>Submit a new blog post</legend>
|
||||||
|
<textarea cols="94" rows=16" name="body">%($"post_arg_body%)</textarea><br />
|
||||||
|
<label>Title: <input size="64" type="text" name="title" value="%($"post_arg_title%)" /></label>
|
||||||
|
<label>Id: <input size="8" type="text" name="id" value="%($"post_arg_id%)" /></label>
|
||||||
|
<label>Date: <input size="10" maxlength="10" type="text" name="date" value="%($"post_date%)" /></label>
|
||||||
|
<input type="submit" value="Post" />
|
||||||
|
</fieldset></form>
|
||||||
|
</div>
|
43
werc/apps/blagh/rss20.tpl
Normal file
43
werc/apps/blagh/rss20.tpl
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
%{
|
||||||
|
fn statpost {
|
||||||
|
f = $1
|
||||||
|
post_uri = `{echo $f | sed 's,^'$sitedir',,'}
|
||||||
|
title=`{read $f/index.md}
|
||||||
|
post_uri=$base_url^`{cleanname `{echo $f | sed -e 's!^'$sitedir'!!'}}^'/'
|
||||||
|
by=`{ls -m $f | sed 's/^\[//g; s/].*$//g' >[2]/dev/null}
|
||||||
|
ifs=() {summary=`{ cat $f/index.md |strip_title_from_md_file| ifs=$difs {$formatter | escape_html} }}
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<atom:link href="%($base_url^$req_path%)" rel="self" type="application/rss+xml" />
|
||||||
|
<title><![CDATA[%($siteTitle%)]]></title>
|
||||||
|
<link>%($base_url^$req_path%)</link>
|
||||||
|
<description><![CDATA[%($blogDesc%)]]></description>
|
||||||
|
<language>en-us</language>
|
||||||
|
<generator><![CDATA[Tom Duff's rc, and Kris Maglione's clever hackery]]></generator>
|
||||||
|
%{
|
||||||
|
# <webMaster>uriel99+rss@gmail.com (Uriel)</webMaster>
|
||||||
|
# rfc2822 last time channel content changed.
|
||||||
|
lbd=`{ndate -m `{date `{mtime `{ls $blagh_root$blagh_dirs/[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]/[0-9] | tail -1} | awk '{print $1}'}}}
|
||||||
|
echo '<lastBuildDate>'$"lbd'</lastBuildDate>'
|
||||||
|
# rfc2822 publication date for content in the channel.
|
||||||
|
pubdate=`{ndate -m}
|
||||||
|
for(f in `{get_post_list $blagh_root$blagh_dirs}){
|
||||||
|
statpost $f
|
||||||
|
%}
|
||||||
|
<item>
|
||||||
|
<title><![CDATA[%($title%)]]></title>
|
||||||
|
<author><![CDATA[%($by%)@noreply.cat-v.org (%($by%))]]></author>
|
||||||
|
<link>%($post_uri%)</link>
|
||||||
|
<guid isPermaLink="true">%($post_uri%)</guid>
|
||||||
|
<pubDate>%($pubdate%)</pubDate>
|
||||||
|
<description> %($summary%) </description>
|
||||||
|
</item>
|
||||||
|
% }
|
||||||
|
</channel>
|
||||||
|
</rss>
|
103
werc/apps/bridge/app.rc
Executable file
103
werc/apps/bridge/app.rc
Executable file
|
@ -0,0 +1,103 @@
|
||||||
|
comment_file_types=(md html)
|
||||||
|
|
||||||
|
fn conf_enable_comments {
|
||||||
|
if(~ $1 -n) {
|
||||||
|
allow_new_user_comments=yes
|
||||||
|
shift
|
||||||
|
}
|
||||||
|
if not if(~ $1 -a) {
|
||||||
|
bridge_anon_comments=yes
|
||||||
|
}
|
||||||
|
enable_comments=yes
|
||||||
|
groups_allowed_comments=$*
|
||||||
|
conf_enable_app bridge
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bridge_init {
|
||||||
|
if(~ $#enable_comments 1 && ! ~ `{ls $local_path.$comment_file_types >[2]/dev/null|wc -l} 0) {
|
||||||
|
|
||||||
|
comments_dir=$sitedir$req_path'_werc/comments'
|
||||||
|
if(~ $REQUEST_METHOD GET && test -d $comments_dir)
|
||||||
|
ll_add handlers_body_foot template apps/bridge/comments_list.tpl
|
||||||
|
|
||||||
|
if(check_user $groups_allowed_comments || {~ $#logged_user 0 && ~ 1 $#allow_new_user_comments $#bridge_anon_comments}) {
|
||||||
|
|
||||||
|
if(~ $#post_arg_bridge_post 1) {
|
||||||
|
ll_add handlers_body_foot template apps/bridge/foot.tpl
|
||||||
|
|
||||||
|
if(mk_new_comment $comments_dir)
|
||||||
|
post_redirect $base_url^$req_path
|
||||||
|
if not
|
||||||
|
saved_comment_text=$post_arg_comment_text
|
||||||
|
}
|
||||||
|
if not if(~ $REQUEST_METHOD GET)
|
||||||
|
ll_add handlers_body_foot template apps/bridge/foot.tpl
|
||||||
|
}
|
||||||
|
if not if(~ $REQUEST_METHOD GET)
|
||||||
|
ll_add handlers_body_foot echo '<hr><p>To post a comment you need to <a href="/_users/login">login</a> first.</p>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_new_user {
|
||||||
|
usr=$1; pass=$2; pass2=$3
|
||||||
|
_status=()
|
||||||
|
|
||||||
|
if(~ $"usr '' || ! echo $usr |sed 1q|grep -s '^'$allowed_user_chars'+$')
|
||||||
|
_status='Requested user name is invalid, must match: '^$allowed_user_chars^'+'
|
||||||
|
if not if(test -d etc/users/$usr)
|
||||||
|
_status='Sorry, user name '''^$usr^''' already taken, please pick a different one.'
|
||||||
|
|
||||||
|
if(~ $"pass '' || ! ~ $"pass $"pass2)
|
||||||
|
_status=($_status 'Provided passwords don''t match.')
|
||||||
|
|
||||||
|
status=$_status
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn mk_new_comment {
|
||||||
|
_status=()
|
||||||
|
dir=$1
|
||||||
|
if(~ $"post_arg_comment_text '')
|
||||||
|
_status='Provide a comment!'
|
||||||
|
if not if(~ $#logged_user 0) {
|
||||||
|
if(! ~ $#allow_new_user_comments 0) {
|
||||||
|
if(validate_new_user $"post_arg_comment_user $post_arg_comment_passwd $post_arg_comment_passwd2) {
|
||||||
|
u=$post_arg_comment_user':'$post_arg_comment_passwd
|
||||||
|
dir=$comments_dir^'_pending'
|
||||||
|
# XXX: This doesn't work because we then do a redirect.
|
||||||
|
notify_notes='Saved comment and registration info, they will be enabled when approved by an admin.'
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
_status=$status
|
||||||
|
}
|
||||||
|
if not if(! ~ $#bridge_anon_comments 0) {
|
||||||
|
if(~ $"post_arg_ima_robot 'not')
|
||||||
|
u='Glenda' # Anonymous
|
||||||
|
if not
|
||||||
|
_status='You are a robot!'
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
_status='You need to log in to comment.'
|
||||||
|
}
|
||||||
|
if not if(check_user $groups_allowed_comments)
|
||||||
|
u=$logged_user
|
||||||
|
if not
|
||||||
|
_status='You are not a member of a group allowed to comment.'
|
||||||
|
|
||||||
|
if(~ $#_status 0) {
|
||||||
|
umask 002
|
||||||
|
|
||||||
|
dir=$dir'/'`{date -n} # FIXME Obvious race
|
||||||
|
mkdir -m 775 -p $dir &&
|
||||||
|
echo $u > $dir/user &&
|
||||||
|
echo $current_date_time > $dir/posted &&
|
||||||
|
echo $post_arg_comment_text > $dir/body
|
||||||
|
_s=$status
|
||||||
|
if(! ~ $"_s '') {
|
||||||
|
dprint 'ERROR XXX: Could not create comment: ' $_s
|
||||||
|
_status='Could not post comment due internal error, sorry.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notify_errors=$_status
|
||||||
|
status=$_status
|
||||||
|
}
|
13
werc/apps/bridge/comments_list.tpl
Executable file
13
werc/apps/bridge/comments_list.tpl
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
<hr>
|
||||||
|
<h2>Comments</h2>
|
||||||
|
|
||||||
|
% for(c in `{ls $comments_dir/}) {
|
||||||
|
% if(test -s $c/body) {
|
||||||
|
<div class="comment">
|
||||||
|
<h5>By: <i>%(`{cat $c/user}%)</i></b> (%(`{cat $c/posted}%))
|
||||||
|
</h5>
|
||||||
|
% cat $c/body | escape_html | sed 's,$,<br>,'
|
||||||
|
<hr></div>
|
||||||
|
% }
|
||||||
|
% }
|
||||||
|
|
37
werc/apps/bridge/foot.tpl
Executable file
37
werc/apps/bridge/foot.tpl
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
% notices_handler
|
||||||
|
<form action="" method="post">
|
||||||
|
<textarea name="comment_text" id="comment_text" cols="80" rows="16">%($"saved_comment_text%)</textarea>
|
||||||
|
<br>
|
||||||
|
<input type="submit" name="bridge_post" value="Post a comment">
|
||||||
|
|
||||||
|
% if(~ $#logged_user 0) {
|
||||||
|
% if(~ $#allow_new_user_comments 1) {
|
||||||
|
<label>New user name:
|
||||||
|
<input type="text" name="comment_user" value="%($"post_arg_comment_user%)">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>Password:
|
||||||
|
<input type="password" name="comment_passwd" value="">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>Repeat password:
|
||||||
|
<input type="password" name="comment_passwd2" value="">
|
||||||
|
</label>
|
||||||
|
<div style="font-size: 70%">
|
||||||
|
Enter your desired user name/password and after your comment has been reviewed by an admin it will be posted and your account will be enabled. If you are already registered please <a href="/_users/login">login</a> before posting.
|
||||||
|
</div>
|
||||||
|
% }
|
||||||
|
% if not if(~ $#bridge_anon_comments 1) {
|
||||||
|
<label>Is <a href="http://glenda.cat-v.org">Glenda a cute bunny</a>?
|
||||||
|
<select name='ima_robot'>
|
||||||
|
<option value="yes">No</option>
|
||||||
|
<option value="not">Yes</option>
|
||||||
|
<option value="foobar">I hate bunnies!</option>
|
||||||
|
<option value="robot">I'm a robot!</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
% }
|
||||||
|
% }
|
||||||
|
</form>
|
40
werc/apps/dirdir/app.rc
Executable file
40
werc/apps/dirdir/app.rc
Executable file
|
@ -0,0 +1,40 @@
|
||||||
|
fn conf_enable_wiki {
|
||||||
|
enable_wiki=yes
|
||||||
|
wiki_editors_groups=$*
|
||||||
|
conf_enable_app dirdir
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dirdir_init {
|
||||||
|
if(! ~ $#enable_wiki 0 && check_user $wiki_editors_groups) {
|
||||||
|
lp=$local_path
|
||||||
|
# werc.rc doesn't append /index when $local_path doesn't exist
|
||||||
|
# maybe it should, but for now we can fix it up here.
|
||||||
|
if(~ $lp */)
|
||||||
|
lp=$lp^'index'
|
||||||
|
dirdir_file=$lp.md
|
||||||
|
dirdir_dir=$dirdir_file^'_werc/dirdir/'
|
||||||
|
|
||||||
|
if(~ 1 $#post_arg_dirdir_edit $#post_arg_dirdir_preview)
|
||||||
|
handler_body_main=(tpl_handler `{get_lib_file dirdir/edit.tpl apps/dirdir/edit.tpl})
|
||||||
|
|
||||||
|
if not if(! ~ '' $"post_arg_dirdir_save $"post_arg_edit_text)
|
||||||
|
save_page
|
||||||
|
|
||||||
|
if not if(~ $"handler_body_main '' || {~ $REQUEST_METHOD GET && test -f $local_path.md})
|
||||||
|
ll_add handlers_bar_left tpl_handler apps/dirdir/sidebar_controls.tpl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_page {
|
||||||
|
dirdir_verdir=$dirdir_dir/^`{date -n}^/
|
||||||
|
mkdir -p $dirdir_verdir
|
||||||
|
umask 002
|
||||||
|
|
||||||
|
# XXX Use a tmp file and mv(1) to ensure updates are atomic?
|
||||||
|
echo $logged_user > $dirdir_verdir/author
|
||||||
|
echo $post_arg_edit_text > $dirdir_verdir/data
|
||||||
|
echo $post_arg_edit_text > $dirdir_file
|
||||||
|
|
||||||
|
post_redirect $base_url^$req_path
|
||||||
|
#notify_notes='Saved <a href="'$"req_path'">'$"req_path'</a>!'
|
||||||
|
}
|
25
werc/apps/dirdir/edit.tpl
Executable file
25
werc/apps/dirdir/edit.tpl
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
<div>
|
||||||
|
<h1>Editing: <a href="%($req_path%)">%($req_path%)</a></h1>
|
||||||
|
<br>
|
||||||
|
<form action="" method="POST">
|
||||||
|
<textarea name="edit_text" id="edit_text" cols="80" rows="43">%{
|
||||||
|
# FIXME Extra trailing new lines get added to the content somehow, should avoid it.
|
||||||
|
if(~ $#post_arg_edit_text 0 && test -f $dirdir_file)
|
||||||
|
cat $dirdir_file | escape_html
|
||||||
|
if not
|
||||||
|
echo -n $post_arg_edit_text | escape_html
|
||||||
|
|
||||||
|
%}</textarea>
|
||||||
|
<br>
|
||||||
|
<input type="submit" name="dirdir_save" value="Save">
|
||||||
|
<input type="submit" name="dirdir_preview" value="Preview">
|
||||||
|
<small>DirDir documents are written using <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a>.</small>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
% if(! ~ $"post_arg_dirdir_preview '') {
|
||||||
|
<h2>Preview:</h2>
|
||||||
|
<div id="preview">
|
||||||
|
% echo $post_arg_edit_text | $formatter
|
||||||
|
</div>
|
||||||
|
% }
|
3
werc/apps/dirdir/sidebar_controls.tpl
Executable file
3
werc/apps/dirdir/sidebar_controls.tpl
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
<form action="" method="POST">
|
||||||
|
<input type="submit" name="dirdir_edit" value="Edit page" />
|
||||||
|
</form>
|
20
werc/apps/duckduckgo/HOWTO
Normal file
20
werc/apps/duckduckgo/HOWTO
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
The default path for site search is /_search/. Assuming you want to keep
|
||||||
|
that default, you could enable site search like so:
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p /www/werc/sites/MYSITE/_search/_werc/
|
||||||
|
echo 'conf_enable_duckduckgo' > /www/werc/sites/MYSITE/_search/_werc/config
|
||||||
|
mkdir -p /www/werc/sites/MYSITE/_werc/lib/
|
||||||
|
cp /www/werc/apps/duckduckgo/footer.inc.sample /www/werc/sites/MYSITE/_werc/lib/footer.inc
|
||||||
|
|
||||||
|
Searches will POST to /_search/ and from there get redirected to Duck Duck
|
||||||
|
Go with a site:$SERVER_NAME prefix. To have the search path URL be some-
|
||||||
|
thing different, you'll have to edit line 23 of app.rc to point to the new
|
||||||
|
path.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* Make it automatically work no matter which directory the app is enabled in.
|
||||||
|
* OR make the search path a configuration option.
|
||||||
|
* Provide a template for non-footer deployment
|
||||||
|
* Enable the search path itself to serve a search form to GET requests
|
||||||
|
|
30
werc/apps/duckduckgo/app.rc
Executable file
30
werc/apps/duckduckgo/app.rc
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
fn conf_enable_duckduckgo {
|
||||||
|
enable_duckduckgo=yes
|
||||||
|
conf_enable_app duckduckgo
|
||||||
|
pageTitle='Site Search'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn duckduckgo_init {
|
||||||
|
get_post_args q
|
||||||
|
if (! ~ $#q 0) {
|
||||||
|
redirect_string = 'https://duckduckgo.com/?q=site:'$SERVER_NAME^'+'^$"q
|
||||||
|
http_redirect $redirect_string '302 Found'
|
||||||
|
}
|
||||||
|
if not {
|
||||||
|
handler_body_main='duckduckgo_body'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn duckduckgo_body {
|
||||||
|
echo '
|
||||||
|
<h1>Site search</h1>
|
||||||
|
<h2>using DuckDuckGo</h2>
|
||||||
|
<form action="/_search/" method="POST">
|
||||||
|
<label for="searchtext">Site search:</label>
|
||||||
|
<input type="text" id="searchtext" name="q" placeholder="Search text...">
|
||||||
|
<input type="submit" value="Search">
|
||||||
|
</form>'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
3
werc/apps/duckduckgo/footer.inc.sample
Normal file
3
werc/apps/duckduckgo/footer.inc.sample
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<div><a href="http://werc.cat-v.org">Powered by werc</a></div>
|
||||||
|
|
||||||
|
<div><form action="/_search/" method="POST"><label for="searchtext">Site search:</label> <input type="text" id="searchtext" name="q" placeholder="Enter search text..."><input type="submit" display="Search"></form></div>
|
10
werc/apps/hello/app.rc
Executable file
10
werc/apps/hello/app.rc
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
fn hello_init {
|
||||||
|
if(~ $req_path /hello) {
|
||||||
|
handler_body_main='hello_body'
|
||||||
|
pageTitle='Hi title!'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hello_body {
|
||||||
|
echo 'Hello world!'
|
||||||
|
}
|
45
werc/apps/paste/app.rc
Executable file
45
werc/apps/paste/app.rc
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
fn conf_enable_wercpaste {
|
||||||
|
paste_url=$conf_wd
|
||||||
|
if (~ $#paste_dir 0) { paste_dir=`{pwd} }
|
||||||
|
conf_enable_app wercpaste
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wercpaste_init {
|
||||||
|
if (~ $REQUEST_METHOD POST && ~ $post_arg_url url && ~ $req_path $paste_url ) { # incoming paste
|
||||||
|
now=`{ date -n }
|
||||||
|
cksum=`{ echo $"post_arg_paste | sum | awk '{ print $1 }' }
|
||||||
|
if (~ $cksum '1715a8eb' ) { # empty paste; discard
|
||||||
|
post_redirect $base_url^$paste_url
|
||||||
|
}
|
||||||
|
if not { # save and redirect
|
||||||
|
# TODO: stop using echo
|
||||||
|
# env var size limit is 16kb, this thing dies with larger input.
|
||||||
|
echo $"post_arg_paste > $paste_dir^/^$now^.^$cksum
|
||||||
|
# uncomment the following line to redirect to the pasted file
|
||||||
|
#post_redirect $base_url^$paste_url^$now^.^$cksum
|
||||||
|
# uncomment the following line instead to just return the url
|
||||||
|
echo 'Content-type: text/plain'; echo ''; exec echo $base_url^$paste_url^$now^.^$cksum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if not { # show a paste if there is one
|
||||||
|
if (test -r $werc_root/$local_path && ~ $QUERY_STRING raw ) {
|
||||||
|
echo 'Content-type: text/plain'; echo ''; exec cat $werc_root/$local_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# drop a textbox
|
||||||
|
if (~ $REQUEST_METHOD GET ) { handler_body_main='begforpaste' }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn begforpaste {
|
||||||
|
echo '<article class="pastebox">
|
||||||
|
<h3 style="text-align: center">pasted data is not publically indexed</h3>
|
||||||
|
<form action="'$paste_url'" method="post" style="margin:2em">
|
||||||
|
<textarea name="paste" cols="120" rows="20" required style="display: block; margin: 0 auto 0 auto" ></textarea><br>
|
||||||
|
<input type="submit" name="submit" value="SUBMIT" style="display: block; margin: 0 auto 0 auto" ><br><br>
|
||||||
|
<span style="display: none"><input type="text" name="url" value="url" > (do not change) </span>
|
||||||
|
</form>
|
||||||
|
</article>
|
||||||
|
'
|
||||||
|
}
|
89
werc/apps/wman/app.rc
Executable file
89
werc/apps/wman/app.rc
Executable file
|
@ -0,0 +1,89 @@
|
||||||
|
fn conf_enable_wman {
|
||||||
|
wman_tmac=an
|
||||||
|
wman_base_uri=$conf_wd
|
||||||
|
wman_man_path=$*
|
||||||
|
if(~ $#wman_man_path 0)
|
||||||
|
wman_man_path=$wman_base_uri
|
||||||
|
conf_enable_app wman
|
||||||
|
}
|
||||||
|
|
||||||
|
wman_junk_filter='/(\/(INDEX|\.cvsignore|_.*)|\.9p|\.html)$/d; s!/man([0-9]+/[^/]+)$!/\1!; '
|
||||||
|
fn wman_ls_pages {
|
||||||
|
ls $* \
|
||||||
|
| sed $dirfilter^$wman_junk_filter^' s/\.([0-9]|9p)$//; s!/0intro$!/intro!' \
|
||||||
|
| sort -u
|
||||||
|
}
|
||||||
|
fn wman_init {
|
||||||
|
ifs=$ifs^'/' { p=`{echo $req_path | sed 's!^'^$wman_base_uri^'!!'} }
|
||||||
|
wman_cat=$p(1)
|
||||||
|
wman_page=$p(2)
|
||||||
|
if(~ $#wman_unix_mode 1) {
|
||||||
|
wman_cp='man'
|
||||||
|
wman_pe=.^$"wman_cat
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! ~ $"wman_cat '') {
|
||||||
|
wman_cat_path=$wman_man_path^/^$"wman_cp^$p(1)
|
||||||
|
if(! ~ $"wman_page '') {
|
||||||
|
wman_page_file=$wman_page^$"wman_pe
|
||||||
|
# Hack to handle 0intro files.
|
||||||
|
if(~ $wman_page intro && test -f $wman_cat_path^/0^$"wman_page_file)
|
||||||
|
wman_page_file=0^$"wman_page_file
|
||||||
|
wman_page_file=$wman_cat_path^/^$"wman_page_file
|
||||||
|
x=`{echo $"req_path|sed 's%.*/([^/]+)/'$"wman_cat'/'^$"wman_page^'%\1%; s%_% %g'}
|
||||||
|
pageTitle=$wman_page' page from Section '$wman_cat' of the '^$"x' manual'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wman_cat_list=`{ls -F $wman_man_path/*/ \
|
||||||
|
| sed -e $wman_junk_filter -e 's!.*/([^/]+)/[^/]+$!\1!; /[0-9]+/!d' \
|
||||||
|
| sort -un}
|
||||||
|
|
||||||
|
synth_paths=($wman_base_uri$wman_cat_list'/')
|
||||||
|
|
||||||
|
if(~ $req_path $wman_base_uri && ~ $"handler_body_main '')
|
||||||
|
handler_body_main=(tpl_handler apps/wman/section_list.tpl)
|
||||||
|
if not if(~ $req_path $wman_base_uri^*) {
|
||||||
|
#^*/[a-z0-9]*[a-z]* $wman_base_uri^*/*[a-z]*[a-z0-9] $wman_base_uri^*/[a-z])
|
||||||
|
if(echo $req_path | grep -s '^'^$wman_base_uri^'/*[0-9]+/[0-9a-z\-\+\.]+$')
|
||||||
|
if(test -f $wman_page_file) # Check for 404
|
||||||
|
handler_body_main=(tpl_handler apps/wman/man_page.tpl)
|
||||||
|
if not if(~ $req_path $wman_base_uri^*/)
|
||||||
|
handler_body_main=(tpl_handler apps/wman/page_list.tpl)
|
||||||
|
if not if(~ $p(2) [A-Z]* [0-9][A-Z]*) # Correct badly capitalized links
|
||||||
|
perm_redirect $wman_base_uri^$p(1)^/^`{echo $p(2) |tr 'A-Z' 'a-z'}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search
|
||||||
|
ll_add handlers_body_head tpl_handler apps/wman/search.tpl
|
||||||
|
if(! ~ $"post_arg_wman_search '') {
|
||||||
|
s=`{echo $post_arg_wman_search | sed 's/[^a-zA-Z0-9\-\.]+//g; s/\.+/./g; 1q'}
|
||||||
|
ifs='' { wman_search_results=`{wman_ls_pages $wman_man_path/*/*^$"s^*} }
|
||||||
|
if(! ~ $"post_arg_go '' && ~ `{echo -n $wman_search_results|wc -l} 1)
|
||||||
|
post_redirect $wman_base_uri^`{echo $wman_search_results|awk -F/ '{print $(NF-1)"/"$NF}'}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wman_get_section_desc {
|
||||||
|
cat $wman_man_path/^$"wman_cp^$1/0intro* >[2]/dev/null| sed '1,2d; s!intro \\- [Ii]ntroduction to !!; 3q;'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wman_page_gen {
|
||||||
|
#troff -manhtml $1| troff2html -t 'Plan 9 from User Space'
|
||||||
|
troff -N -m$wman_tmac $1 | wman_out_filter
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wman_out_filter {
|
||||||
|
wman_default_out_filter
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wman_default_out_filter {
|
||||||
|
# col -x syntax is the same for UNIX and Plan 9.
|
||||||
|
escape_html \
|
||||||
|
| sed 's!([\.\-a-zA-Z0-9]+)\(('^`{echo $wman_cat_list|tr ' ' '|'}^')\)!<a href="../\2/\1">&</a>!g' \
|
||||||
|
| awk '/^$/ {if(n != 1) print; n=1; next} /./ {n=0; print}' \
|
||||||
|
| col -x
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3
werc/apps/wman/man_page.tpl
Executable file
3
werc/apps/wman/man_page.tpl
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
<pre>
|
||||||
|
% wman_page_gen $wman_page_file
|
||||||
|
</pre>
|
11
werc/apps/wman/page_list.tpl
Executable file
11
werc/apps/wman/page_list.tpl
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
% d=`{wman_get_section_desc $wman_cat}
|
||||||
|
<h1>Manual pages - Section %($wman_cat%): %($"d%)</h1>
|
||||||
|
|
||||||
|
<ul style="float:left">
|
||||||
|
%{
|
||||||
|
wman_ls_pages $wman_cat_path \
|
||||||
|
| awk -F/ '{ print "<li><a href=\""$(NF)"\">"$(NF)"</a></li>" }
|
||||||
|
NR%20 == 0 { print "</ul><ul style=\"float: left\">" }'
|
||||||
|
%}
|
||||||
|
</ul>
|
||||||
|
|
20
werc/apps/wman/search.tpl
Executable file
20
werc/apps/wman/search.tpl
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
<form action="" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<input type="text" name="wman_search" value="%($"s%)" />
|
||||||
|
<input type="submit" name="go" value="Feel Lucky" />
|
||||||
|
<input type="submit" value="Search" />
|
||||||
|
|
||||||
|
% if(! ~ $"post_arg_wman_search '') {
|
||||||
|
% if(~ $"wman_search_results '') {
|
||||||
|
No matches found for <i>'%($post_arg_wman_search%)'</i>.
|
||||||
|
% }
|
||||||
|
% if not {
|
||||||
|
<ul>
|
||||||
|
% echo $wman_search_results|awk -F/ '$(NF-1) ~ "^[0-9]+$" {printf "<li><a href=\"'$wman_base_uri'%s/%s\" />%s(%s)</a></li>", $(NF-1),$NF, $NF, $(NF-1)}'
|
||||||
|
</ul>
|
||||||
|
% }
|
||||||
|
% }
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
|
11
werc/apps/wman/section_list.tpl
Executable file
11
werc/apps/wman/section_list.tpl
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
<h1>Manual Sections</h1>
|
||||||
|
|
||||||
|
<ul style="text-transform: capitalize;">
|
||||||
|
% for(c in $wman_cat_list) {
|
||||||
|
<li><a href="%($c%)/"><b>Section: %($c%)</b></a>
|
||||||
|
% wman_get_section_desc $c
|
||||||
|
% if(~ $status '' '|')
|
||||||
|
% echo '(<a href="'$c'/intro">intro</a>)'
|
||||||
|
</li>
|
||||||
|
% }
|
||||||
|
</ul>
|
33
werc/bin/aux/addwuser.rc
Executable file
33
werc/bin/aux/addwuser.rc
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/rc
|
||||||
|
|
||||||
|
if(! ~ $#werc_root 0)
|
||||||
|
cd $werc_root
|
||||||
|
|
||||||
|
fn usage {
|
||||||
|
if(! ~ $#* 0)
|
||||||
|
echo $0: $* >[1=2]
|
||||||
|
echo 'Usage:' $0 'user_name user_password [groups ...]' >[1=2]
|
||||||
|
exit usage
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! test -d etc/users/)
|
||||||
|
usage 'Run for root of werc installation or set $werc_root'
|
||||||
|
|
||||||
|
user_name=$1
|
||||||
|
shift
|
||||||
|
user_pass=$1
|
||||||
|
shift
|
||||||
|
user_groups=$*
|
||||||
|
|
||||||
|
if(~ $"user_name '' || ~ $"user_pass '')
|
||||||
|
usage
|
||||||
|
|
||||||
|
mkdir etc/users/$user_name
|
||||||
|
echo $user_pass > etc/users/$user_name/password
|
||||||
|
|
||||||
|
if(! ~ $#user_groups 0)
|
||||||
|
for(g in $user_groups) {
|
||||||
|
mkdir -p etc/users/$g
|
||||||
|
echo $user_name >> etc/users/$g/members
|
||||||
|
}
|
||||||
|
|
64
werc/bin/aux/bpst.rc
Executable file
64
werc/bin/aux/bpst.rc
Executable file
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/rc
|
||||||
|
|
||||||
|
path=( $PLAN9/bin $path )
|
||||||
|
base=.
|
||||||
|
|
||||||
|
if(~ $#user 0)
|
||||||
|
user=`{whoami}
|
||||||
|
|
||||||
|
file=(); title=();
|
||||||
|
bloguser=$user
|
||||||
|
while(! ~ $#* 0) {
|
||||||
|
switch($1) {
|
||||||
|
case -u
|
||||||
|
base=/gsoc/www/people/$user/blog/
|
||||||
|
case -b
|
||||||
|
shift
|
||||||
|
base=$1
|
||||||
|
case -f
|
||||||
|
shift
|
||||||
|
file=$1
|
||||||
|
}
|
||||||
|
shift
|
||||||
|
}
|
||||||
|
|
||||||
|
if(~ $"EDITOR '')
|
||||||
|
EDITOR=vi
|
||||||
|
|
||||||
|
if(~ $#file 0 || ! test -f $file) {
|
||||||
|
file=/tmp/blogtmp.$pid
|
||||||
|
rm $file >[2]/dev/null
|
||||||
|
touch $file
|
||||||
|
}
|
||||||
|
|
||||||
|
$EDITOR $file
|
||||||
|
ispell $file
|
||||||
|
rm $file.bak >[2]/dev/null
|
||||||
|
|
||||||
|
fn mkbpost {
|
||||||
|
umask 002 # Let group write
|
||||||
|
bptext=$1
|
||||||
|
if(! ~ $#2 0)
|
||||||
|
bpid=`{echo -n '-'^$"bpid | sed 's/'$forbidden_uri_chars'+/_/g; 1q'}
|
||||||
|
d=`{/bin/date +%F|sed 's,-,/,g'}
|
||||||
|
|
||||||
|
ddir=$blagh_root^$d^'/'
|
||||||
|
n=`{ls $ddir >[2]/dev/null |wc -l}
|
||||||
|
|
||||||
|
mkdir -p $ddir/$"n^$"bpid/
|
||||||
|
{
|
||||||
|
# TODO: Enable metadata
|
||||||
|
#echo '* Posted:' `{date}
|
||||||
|
#if(! ~ $#logged_user 0)
|
||||||
|
# echo '* Author: '$logged_user
|
||||||
|
cat $bptext
|
||||||
|
}> $ddir/$"n^$"bpid/index.md
|
||||||
|
}
|
||||||
|
|
||||||
|
forbidden_uri_chars='[^a-zA-Z0-9_+\-\/\.]'
|
||||||
|
blagh_root=$base
|
||||||
|
|
||||||
|
if(test -s $file)
|
||||||
|
mkbpost $file
|
||||||
|
if not
|
||||||
|
echo Empty file!
|
14
werc/bin/aux/gensitemaptxt.rc
Executable file
14
werc/bin/aux/gensitemaptxt.rc
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/rc
|
||||||
|
# DEPRECATED: sitemap.tpl now generates and updates a sitemap.txt when requested, and is also more smart than this simplistic script.
|
||||||
|
|
||||||
|
for(d in sites/*/) {
|
||||||
|
echo $d
|
||||||
|
9 du -a $d | awk '/\.(md|html)$/ { print $2 }; {}' | 9 sed -e 's/\.(md|html)$//' -e 's,/index$,/,' -e 's,^sites/,http://,' > $d/sitemap.txt
|
||||||
|
|
||||||
|
if(! test -f $d/robots.txt) {
|
||||||
|
echo generating missing robots.txt for $d
|
||||||
|
echo $d|sed 's,sites/,Sitemap: http://,; s/$/sitemap.txt/;' > $d/robots.txt
|
||||||
|
cat $d/robots.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
werc/bin/aux/runtsts.rc
Executable file
16
werc/bin/aux/runtsts.rc
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/rc
|
||||||
|
|
||||||
|
tstdom='http://test.cat-v.org'
|
||||||
|
|
||||||
|
cd sites/tst.cat-v.org
|
||||||
|
|
||||||
|
tstfiles=`{du -a |awk '/\.tst$/ { print $2 }; {} ' | sed 's/^\.//; s/\.tst$//'}
|
||||||
|
|
||||||
|
for(f in $tstfiles) {
|
||||||
|
ifs='
|
||||||
|
' { tsts=`{cat ./$f.tst} }
|
||||||
|
|
||||||
|
for(t in $tsts) {
|
||||||
|
echo tst $t
|
||||||
|
}
|
||||||
|
}
|
236
werc/bin/cgilib.rc
Executable file
236
werc/bin/cgilib.rc
Executable file
|
@ -0,0 +1,236 @@
|
||||||
|
# Useful CGI stuff
|
||||||
|
|
||||||
|
fn dprint { echo $* >[1=2] }
|
||||||
|
fn dprintv { { for(v in $*) { echo -n $v^'#'^$#$v^'=' $$v '; ' }; echo } >[1=2] }
|
||||||
|
fn echo {if(! ~ $1 -n || ! ~ $2 '') /bin/echo $*}
|
||||||
|
fn escape_html { sed 's/&/\&/g; s/</\</g; s/>/\>/g' $* }
|
||||||
|
|
||||||
|
fn http_redirect {
|
||||||
|
if(~ $1 http://* https://*)
|
||||||
|
t=$1
|
||||||
|
if not if(~ $1 /*)
|
||||||
|
t=$"base_url^$1
|
||||||
|
if not
|
||||||
|
t=$"base_url^$"req_path^$1
|
||||||
|
exec /bin/echo 'Status: '^$2^'
|
||||||
|
Location: '^$t^'
|
||||||
|
|
||||||
|
'
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
fn perm_redirect { http_redirect $1 '301 Moved Permanantly' }
|
||||||
|
fn post_redirect { http_redirect $1 '303 See Other' }
|
||||||
|
|
||||||
|
|
||||||
|
# Note: should check if content type is application/x-www-form-urlencoded?
|
||||||
|
# Should compare with http://www.shelldorado.com/scripts/cmds/urlgetopt.txt
|
||||||
|
fn load_post_args {
|
||||||
|
if(~ $REQUEST_METHOD POST && ~ $#post_args 0) {
|
||||||
|
ifs='&
|
||||||
|
' for(pair in `{cat}) {
|
||||||
|
ifs='=' { pair=`{echo -n $pair} }
|
||||||
|
n='post_arg_'^`{echo $pair(1)|nurldecode|tr -cd 'a-zA-Z0-9_'}
|
||||||
|
post_args=( $post_args $n )
|
||||||
|
ifs=() { $n=`{echo -n $pair(2)|nurldecode|tr -d '
'} }
|
||||||
|
}
|
||||||
|
pair=()
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
status='No POST or post args already loaded'
|
||||||
|
}
|
||||||
|
# Status is () if at least one arg is found. DEPRECATED: access vars directly.
|
||||||
|
fn get_post_args {
|
||||||
|
load_post_args
|
||||||
|
_status='No post arg matches'
|
||||||
|
for(n in $*) {
|
||||||
|
v=post_arg_$n
|
||||||
|
if(! ~ $#$v 0) {
|
||||||
|
$n=$$v
|
||||||
|
_status=()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status=$_status
|
||||||
|
}
|
||||||
|
|
||||||
|
# This seems slightly improve performance, but might depend on httpd buffering behavior.
|
||||||
|
fn awk_buffer {
|
||||||
|
awk '{
|
||||||
|
buf = buf $0"\n"
|
||||||
|
if(length(buf) > 1400) {
|
||||||
|
printf "%s", buf
|
||||||
|
buf = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { printf "%s", buf }'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nurldecode { urlencode -d || url_decode} # GROSS
|
||||||
|
|
||||||
|
fn url_decode {
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
hextab ["0"] = 0; hextab ["8"] = 8;
|
||||||
|
hextab ["1"] = 1; hextab ["9"] = 9;
|
||||||
|
hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10
|
||||||
|
hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11;
|
||||||
|
hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12;
|
||||||
|
hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13;
|
||||||
|
hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14;
|
||||||
|
hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
decoded = ""
|
||||||
|
i = 1
|
||||||
|
len = length ($0)
|
||||||
|
while ( i <= len ) {
|
||||||
|
c = substr ($0, i, 1)
|
||||||
|
if ( c == "%" ) {
|
||||||
|
if ( i+2 <= len ) {
|
||||||
|
c1 = substr ($0, i+1, 1)
|
||||||
|
c2 = substr ($0, i+2, 1)
|
||||||
|
if ( hextab [c1] == "" || hextab [c2] == "" ) {
|
||||||
|
print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2"
|
||||||
|
} else {
|
||||||
|
code = 0 + hextab [c1] * 16 + hextab [c2] + 0
|
||||||
|
c = sprintf ("%c", code)
|
||||||
|
i = i + 2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print "WARNING: invalid % encoding: " substr ($0, i, len - i)
|
||||||
|
}
|
||||||
|
} else if ( c == "+" ) {
|
||||||
|
c = " "
|
||||||
|
}
|
||||||
|
decoded = decoded c
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
printf "%s", decoded
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nurlencode { urlencode || url_encode } # GROSS
|
||||||
|
|
||||||
|
fn url_encode {
|
||||||
|
awk '
|
||||||
|
BEGIN {
|
||||||
|
# We assume an awk implementation that is just plain dumb.
|
||||||
|
# We will convert an character to its ASCII value with the
|
||||||
|
# table ord[], and produce two-digit hexadecimal output
|
||||||
|
# without the printf("%02X") feature.
|
||||||
|
|
||||||
|
EOL = "%0A" # "end of line" string (encoded)
|
||||||
|
split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ")
|
||||||
|
hextab [0] = 0
|
||||||
|
for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
|
||||||
|
if ("'^$"EncodeEOL^'" == "yes") EncodeEOL = 1; else EncodeEOL = 0
|
||||||
|
}
|
||||||
|
{
|
||||||
|
encoded = ""
|
||||||
|
for ( i=1; i<=length ($0); ++i ) {
|
||||||
|
c = substr ($0, i, 1)
|
||||||
|
if ( c ~ /[a-zA-Z0-9.-]/ ) {
|
||||||
|
encoded = encoded c # safe character
|
||||||
|
} else if ( c == " " ) {
|
||||||
|
encoded = encoded "+" # special handling
|
||||||
|
} else {
|
||||||
|
# unsafe character, encode it as a two-digit hex-number
|
||||||
|
lo = ord [c] % 16
|
||||||
|
hi = int (ord [c] / 16);
|
||||||
|
encoded = encoded "%" hextab [hi] hextab [lo]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( EncodeEOL ) {
|
||||||
|
printf ("%s", encoded EOL)
|
||||||
|
} else {
|
||||||
|
print encoded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
#if ( EncodeEOL ) print ""
|
||||||
|
}
|
||||||
|
' $*
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cookies
|
||||||
|
fn set_cookie {
|
||||||
|
# TODO: should check input values more carefully
|
||||||
|
name=$1
|
||||||
|
val=$2
|
||||||
|
extraHttpHeaders=( $extraHttpHeaders 'Set-cookie: '^$"name^'='^$"val^'; path=/;' )
|
||||||
|
}
|
||||||
|
fn get_cookie {
|
||||||
|
ifs=';' { co=`{echo $HTTP_COOKIE} }
|
||||||
|
|
||||||
|
# XXX: we might be adding a trailing new line?
|
||||||
|
# The ' ?' is needed to deal with '; ' inter-cookie delimiter
|
||||||
|
{ for(c in $co) echo $c } | sed -n 's/^ ?'$1'=//p'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn static_file {
|
||||||
|
echo -n 'Content-Type: '
|
||||||
|
select_mime $1
|
||||||
|
echo
|
||||||
|
exec cat $1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_mime {
|
||||||
|
m='text/plain'
|
||||||
|
if(~ $1 *.css)
|
||||||
|
m='text/css'
|
||||||
|
if not if(~ $1 *.ico)
|
||||||
|
m='image/x-icon'
|
||||||
|
if not if(~ $1 *.png)
|
||||||
|
m='image/png'
|
||||||
|
if not if(~ $1 *.jpg *.jpeg)
|
||||||
|
m='image/jpeg'
|
||||||
|
if not if(~ $1 *.gif)
|
||||||
|
m='image/gif'
|
||||||
|
if not if(~ $1 *.pdf)
|
||||||
|
m='application/pdf'
|
||||||
|
echo $m
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Generic rc programming helpers
|
||||||
|
|
||||||
|
# Manage nested lists
|
||||||
|
fn ll_add {
|
||||||
|
_l=$1^_^$#$1
|
||||||
|
$_l=$*(2-)
|
||||||
|
$1=( $$1 $_l )
|
||||||
|
}
|
||||||
|
# Add to the head: dangerous if you shrink list by hand!
|
||||||
|
fn ll_addh {
|
||||||
|
_l=$1^_^$#$1
|
||||||
|
$_l=$*(2-)
|
||||||
|
$1=( $_l $$1 )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NEW_LINE='
|
||||||
|
'
|
||||||
|
|
||||||
|
# crop_text [max_lenght [ellipsis]]
|
||||||
|
# TODO: Option to crop only at word-delimiters.
|
||||||
|
fn crop_text {
|
||||||
|
m=512
|
||||||
|
e='...'
|
||||||
|
if(! ~ $#1 0)
|
||||||
|
m=$1
|
||||||
|
if(! ~ $#2 0)
|
||||||
|
e=$2
|
||||||
|
|
||||||
|
awk -v 'max='^$"m -v 'ellipsis='$e '
|
||||||
|
{
|
||||||
|
nc += 1 + length;
|
||||||
|
if(nc > max) {
|
||||||
|
print substr($0, 1, nc - max) " " ellipsis
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
print
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
27
werc/bin/contrib/fix-rc-scripts
Executable file
27
werc/bin/contrib/fix-rc-scripts
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/local/plan9/bin/rc
|
||||||
|
|
||||||
|
# Fix rc shell scripts to find rc without launching env every time.
|
||||||
|
# Invoke with rc and plan9 versions of grep and ed in $PATH
|
||||||
|
|
||||||
|
# If your system lacks which (e.g. some gnu/linux)
|
||||||
|
# substitute the full path to rc in this line:
|
||||||
|
rc=/usr/local/plan9/bin/rc
|
||||||
|
firstline='#!'$"rc
|
||||||
|
|
||||||
|
if(~ $#* 0) files = *
|
||||||
|
if not files = $*
|
||||||
|
|
||||||
|
myname = `{basename $0}
|
||||||
|
|
||||||
|
for(file in $files) {
|
||||||
|
if(test -d $file) $0 $file/*
|
||||||
|
if not if(~ $file *$myname) {}
|
||||||
|
if not if(sed 1q $file | grep '^#!/.*[/ ]rc$' > /dev/null) {
|
||||||
|
{
|
||||||
|
echo 1c
|
||||||
|
echo $firstline
|
||||||
|
echo .
|
||||||
|
echo wq
|
||||||
|
} | ed $file > /dev/null
|
||||||
|
}
|
||||||
|
}
|
12
werc/bin/contrib/hgweb.config
Executable file
12
werc/bin/contrib/hgweb.config
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
[web]
|
||||||
|
style = gitweb
|
||||||
|
allow_archive = bz2
|
||||||
|
|
||||||
|
#[paths]
|
||||||
|
#w9 = /gsoc/hg/w9/
|
||||||
|
|
||||||
|
[collections]
|
||||||
|
#allow_archive = bz2 zip
|
||||||
|
/gsoc/hg = /gsoc/hg/
|
||||||
|
#/var/hg = /var/hg/
|
||||||
|
|
47
werc/bin/contrib/hgwebdir.cgi
Executable file
47
werc/bin/contrib/hgwebdir.cgi
Executable file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# An example CGI script to export multiple hgweb repos, edit as necessary
|
||||||
|
|
||||||
|
# send python tracebacks to the browser if an error occurs:
|
||||||
|
import cgitb
|
||||||
|
cgitb.enable()
|
||||||
|
|
||||||
|
# adjust python path if not a system-wide install:
|
||||||
|
#import sys
|
||||||
|
#sys.path.insert(0, "/path/to/python/lib")
|
||||||
|
|
||||||
|
# If you'd like to serve pages with UTF-8 instead of your default
|
||||||
|
# locale charset, you can do so by uncommenting the following lines.
|
||||||
|
# Note that this will cause your .hgrc files to be interpreted in
|
||||||
|
# UTF-8 and all your repo files to be displayed using UTF-8.
|
||||||
|
#
|
||||||
|
#import os
|
||||||
|
#os.environ["HGENCODING"] = "UTF-8"
|
||||||
|
|
||||||
|
from mercurial.hgweb.hgwebdir_mod import hgwebdir
|
||||||
|
from mercurial.hgweb.request import wsgiapplication
|
||||||
|
import mercurial.hgweb.wsgicgi as wsgicgi
|
||||||
|
|
||||||
|
# The config file looks like this. You can have paths to individual
|
||||||
|
# repos, collections of repos in a directory tree, or both.
|
||||||
|
#
|
||||||
|
# [paths]
|
||||||
|
# virtual/path = /real/path
|
||||||
|
# virtual/path = /real/path
|
||||||
|
#
|
||||||
|
# [collections]
|
||||||
|
# /prefix/to/strip/off = /root/of/tree/full/of/repos
|
||||||
|
#
|
||||||
|
# collections example: say directory tree /foo contains repos /foo/bar,
|
||||||
|
# /foo/quux/baz. Give this config section:
|
||||||
|
# [collections]
|
||||||
|
# /foo = /foo
|
||||||
|
# Then repos will list as bar and quux/baz.
|
||||||
|
#
|
||||||
|
# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
|
||||||
|
# or use a dictionary with entries like 'virtual/path': '/real/path'
|
||||||
|
|
||||||
|
def make_web_app():
|
||||||
|
return hgwebdir("hgweb.config")
|
||||||
|
|
||||||
|
wsgicgi.launch(wsgiapplication(make_web_app))
|
1447
werc/bin/contrib/markdown.pl
Executable file
1447
werc/bin/contrib/markdown.pl
Executable file
File diff suppressed because it is too large
Load diff
427
werc/bin/contrib/md2html.awk
Executable file
427
werc/bin/contrib/md2html.awk
Executable file
|
@ -0,0 +1,427 @@
|
||||||
|
#!/bin/awk -f
|
||||||
|
#
|
||||||
|
# by: Jesus Galan (yiyus) 2009
|
||||||
|
#
|
||||||
|
# Usage: md2html.awk file.md > file.html
|
||||||
|
# See: http://4l77.com/src/md2html.awk
|
||||||
|
|
||||||
|
function eschtml(t) {
|
||||||
|
gsub("&", "\\&", t);
|
||||||
|
gsub("<", "\\<", t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
function oprint(t){
|
||||||
|
if(nr == 0)
|
||||||
|
print t;
|
||||||
|
else
|
||||||
|
otext = otext "\n" t;
|
||||||
|
}
|
||||||
|
|
||||||
|
function subref(id){
|
||||||
|
for(; nr > 0 && sub("<<" id, ref[id], otext); nr--);
|
||||||
|
if(nr == 0 && otext) {
|
||||||
|
print otext;
|
||||||
|
otext = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextil(t) {
|
||||||
|
if(!match(t, /[`<&\[*_\\-]|(\!\[)/))
|
||||||
|
return t;
|
||||||
|
t1 = substr(t, 1, RSTART - 1);
|
||||||
|
tag = substr(t, RSTART, RLENGTH);
|
||||||
|
t2 = substr(t, RSTART + RLENGTH);
|
||||||
|
if(ilcode && tag != "`")
|
||||||
|
return eschtml(t1 tag) nextil(t2);
|
||||||
|
# Backslash escaping
|
||||||
|
if(tag == "\\"){
|
||||||
|
if(match(t2, /^[\\`*_{}\[\]()#+\-\.!]/)){
|
||||||
|
tag = substr(t2, 1, 1);
|
||||||
|
t2 = substr(t2, 2);
|
||||||
|
}
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
}
|
||||||
|
# Dashes
|
||||||
|
if(tag == "-"){
|
||||||
|
if(sub(/^-/, "", t2))
|
||||||
|
tag = "—";
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
}
|
||||||
|
# Inline Code
|
||||||
|
if(tag == "`"){
|
||||||
|
if(sub(/^`/, "", t2)){
|
||||||
|
if(!match(t2, /``/))
|
||||||
|
return t1 "”" nextil(t2);
|
||||||
|
ilcode2 = !ilcode2;
|
||||||
|
}
|
||||||
|
else if(ilcode2)
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
tag = "<code>";
|
||||||
|
if(ilcode){
|
||||||
|
t1 = eschtml(t1);
|
||||||
|
tag = "</code>";
|
||||||
|
}
|
||||||
|
ilcode = !ilcode;
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
}
|
||||||
|
if(tag == "<"){
|
||||||
|
# Autolinks
|
||||||
|
if(match(t2, /^[^ ]+[\.@][^ ]+>/)){
|
||||||
|
url = eschtml(substr(t2, 1, RLENGTH - 1));
|
||||||
|
t2 = substr(t2, RLENGTH + 1);
|
||||||
|
linktext = url;
|
||||||
|
if(match(url, /@/) && !match(url, /^mailto:/))
|
||||||
|
url = "mailto:" url;
|
||||||
|
return t1 "<a href=\"" url "\">" linktext "</a>" nextil(t2);
|
||||||
|
}
|
||||||
|
# Html tags
|
||||||
|
if(match(t2, /^[A-Za-z\/!][^>]*>/)){
|
||||||
|
tag = tag substr(t2, RSTART, RLENGTH);
|
||||||
|
t2 = substr(t2, RLENGTH + 1);
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
}
|
||||||
|
return t1 "<" nextil(t2);
|
||||||
|
}
|
||||||
|
# Html special entities
|
||||||
|
if(tag == "&"){
|
||||||
|
if(match(t2, /^#?[A-Za-z0-9]+;/)){
|
||||||
|
tag = tag substr(t2, RSTART, RLENGTH);
|
||||||
|
t2 = substr(t2, RLENGTH + 1);
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
}
|
||||||
|
return t1 "&" nextil(t2);
|
||||||
|
}
|
||||||
|
# Images
|
||||||
|
if(tag == "!["){
|
||||||
|
if(!match(t2, /(\[.*\])|(\(.*\))/))
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
match(t2, /^[^\]]*/);
|
||||||
|
alt = substr(t2, 1, RLENGTH);
|
||||||
|
t2 = substr(t2, RLENGTH + 2);
|
||||||
|
if(match(t2, /^\(/)){
|
||||||
|
# Inline
|
||||||
|
sub(/^\(/, "", t2);
|
||||||
|
match(t2, /^[^\)]+/);
|
||||||
|
url = eschtml(substr(t2, 1, RLENGTH));
|
||||||
|
t2 = substr(t2, RLENGTH + 2);
|
||||||
|
title = "";
|
||||||
|
if(match(url, /[ ]+\".*\"[ ]*$/)) {
|
||||||
|
title = substr(url, RSTART, RLENGTH);
|
||||||
|
url = substr(url, 1, RSTART - 1);
|
||||||
|
match(title, /\".*\"/);
|
||||||
|
title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\"";
|
||||||
|
}
|
||||||
|
if(match(url, /^<.*>$/))
|
||||||
|
url = substr(url, 2, RLENGTH - 2);
|
||||||
|
return t1 "<img src=\"" url "\" alt=\"" alt "\"" title " />" nextil(t2);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
# Referenced
|
||||||
|
sub(/^ ?\[/, "", t2);
|
||||||
|
id = alt;
|
||||||
|
if(match(t2, /^[^\]]+/))
|
||||||
|
id = substr(t2, 1, RLENGTH);
|
||||||
|
t2 = substr(t2, RLENGTH + 2);
|
||||||
|
if(ref[id])
|
||||||
|
r = ref[id];
|
||||||
|
else{
|
||||||
|
r = "<<" id;
|
||||||
|
nr++;
|
||||||
|
}
|
||||||
|
return t1 "<img src=\"" r "\" alt=\"" alt "\" />" nextil(t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Links
|
||||||
|
if(tag == "["){
|
||||||
|
if(!match(t2, /(\[.*\])|(\(.*\))/))
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
match(t2, /^[^\]]*(\[[^\]]*\][^\]]*)*/);
|
||||||
|
linktext = substr(t2, 1, RLENGTH);
|
||||||
|
t2 = substr(t2, RLENGTH + 2);
|
||||||
|
if(match(t2, /^\(/)){
|
||||||
|
# Inline
|
||||||
|
match(t2, /^[^\)]+(\([^\)]+\)[^\)]*)*/);
|
||||||
|
url = substr(t2, 2, RLENGTH - 1);
|
||||||
|
pt2 = substr(t2, RLENGTH + 2);
|
||||||
|
title = "";
|
||||||
|
if(match(url, /[ ]+\".*\"[ ]*$/)) {
|
||||||
|
title = substr(url, RSTART, RLENGTH);
|
||||||
|
url = substr(url, 1, RSTART - 1);
|
||||||
|
match(title, /\".*\"/);
|
||||||
|
title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\"";
|
||||||
|
}
|
||||||
|
if(match(url, /^<.*>$/))
|
||||||
|
url = substr(url, 2, RLENGTH - 2);
|
||||||
|
url = eschtml(url);
|
||||||
|
return t1 "<a href=\"" url "\"" title ">" nextil(linktext) "</a>" nextil(pt2);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
# Referenced
|
||||||
|
sub(/^ ?\[/, "", t2);
|
||||||
|
id = linktext;
|
||||||
|
if(match(t2, /^[^\]]+/))
|
||||||
|
id = substr(t2, 1, RLENGTH);
|
||||||
|
t2 = substr(t2, RLENGTH + 2);
|
||||||
|
if(ref[id])
|
||||||
|
r = ref[id];
|
||||||
|
else{
|
||||||
|
r = "<<" id;
|
||||||
|
nr++;
|
||||||
|
}
|
||||||
|
pt2 = t2;
|
||||||
|
return t1 "<a href=\"" r "\" />" nextil(linktext) "</a>" nextil(pt2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Emphasis
|
||||||
|
if(match(tag, /[*_]/)){
|
||||||
|
ntag = tag;
|
||||||
|
if(sub("^" tag, "", t2)){
|
||||||
|
if(stag[ns] == tag && match(t2, "^" tag))
|
||||||
|
t2 = tag t2;
|
||||||
|
else
|
||||||
|
ntag = tag tag
|
||||||
|
}
|
||||||
|
n = length(ntag);
|
||||||
|
tag = (n == 2) ? "strong" : "em";
|
||||||
|
if(match(t1, / $/) && match(t2, /^ /))
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
if(stag[ns] == ntag){
|
||||||
|
tag = "/" tag;
|
||||||
|
ns--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stag[++ns] = ntag;
|
||||||
|
tag = "<" tag ">";
|
||||||
|
return t1 tag nextil(t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline(t) {
|
||||||
|
ilcode = 0;
|
||||||
|
ilcode2 = 0;
|
||||||
|
ns = 0;
|
||||||
|
|
||||||
|
return nextil(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printp(tag) {
|
||||||
|
if(!match(text, /^[ ]*$/)){
|
||||||
|
text = inline(text);
|
||||||
|
if(tag != "")
|
||||||
|
oprint("<" tag ">" text "</" tag ">");
|
||||||
|
else
|
||||||
|
oprint(text);
|
||||||
|
}
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
blank = 0;
|
||||||
|
code = 0;
|
||||||
|
hr = 0;
|
||||||
|
html = 0;
|
||||||
|
nl = 0;
|
||||||
|
nr = 0;
|
||||||
|
otext = "";
|
||||||
|
text = "";
|
||||||
|
par = "p";
|
||||||
|
}
|
||||||
|
|
||||||
|
# References
|
||||||
|
!code && /^ *\[[^\]]*\]:[ ]+/ {
|
||||||
|
sub(/^ *\[/, "");
|
||||||
|
match($0, /\]/);
|
||||||
|
id = substr($0, 1, RSTART - 1);
|
||||||
|
sub(id "\\]:[ ]+", "");
|
||||||
|
title = "";
|
||||||
|
if(match($0, /\".*\"$/))
|
||||||
|
title = "\" title=\"" substr($0, RSTART + 1, RLENGTH - 2);
|
||||||
|
sub(/[ ]+\".*\"$/, "");
|
||||||
|
url = eschtml($0);
|
||||||
|
ref[id] = url title;
|
||||||
|
|
||||||
|
subref(id);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# html
|
||||||
|
!html && /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\
|
||||||
|
isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/ {
|
||||||
|
if(code)
|
||||||
|
oprint("</pre></code>");
|
||||||
|
for(; !text && block[nl] == "blockquote"; nl--)
|
||||||
|
oprint("</blockquote>");
|
||||||
|
match($0, /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\
|
||||||
|
isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/);
|
||||||
|
htag = substr($0, 2, RLENGTH - 1);
|
||||||
|
if(!match($0, "(<\\/" htag ">)|((^<hr ?\\/?)|(--)>$)"))
|
||||||
|
html = 1;
|
||||||
|
if(html && match($0, /^<hr/))
|
||||||
|
hr = 1;
|
||||||
|
oprint($0);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
html && (/(^<\/(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\
|
||||||
|
isindex|menu|noframes|noscript|ol|p|pre|table|ul).*)|(--)>$/ ||
|
||||||
|
(hr && />$/)) {
|
||||||
|
html = 0;
|
||||||
|
hr = 0;
|
||||||
|
oprint($0);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
oprint($0);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# List and quote blocks
|
||||||
|
|
||||||
|
# Remove indentation
|
||||||
|
{
|
||||||
|
for(nnl = 0; nnl < nl; nnl++)
|
||||||
|
if((match(block[nnl + 1], /[ou]l/) && !sub(/^( | )/, "")) || \
|
||||||
|
(block[nnl + 1] == "blockquote" && !sub(/^> ?/, "")))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nnl < nl && !blank && text && ! /^ ? ? ?([*+-]|([0-9]+\.)+)( +| )/ { nnl = nl; }
|
||||||
|
# Quote blocks
|
||||||
|
{
|
||||||
|
while(sub(/^> /, ""))
|
||||||
|
nblock[++nnl] = "blockquote";
|
||||||
|
}
|
||||||
|
# Horizontal rules
|
||||||
|
{ hr = 0; }
|
||||||
|
(blank || (!text && !code)) && /^ ? ? ?([-*_][ ]*)([-*_][ ]*)([-*_][ ]*)+$/ {
|
||||||
|
if(code){
|
||||||
|
oprint("</pre></code>");
|
||||||
|
code = 0;
|
||||||
|
}
|
||||||
|
blank = 0;
|
||||||
|
nnl = 0;
|
||||||
|
hr = 1;
|
||||||
|
}
|
||||||
|
# List items
|
||||||
|
block[nl] ~ /[ou]l/ && /^$/ {
|
||||||
|
blank = 1;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
{ newli = 0; }
|
||||||
|
!hr && (nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?[*+-]( +| )/ {
|
||||||
|
sub(/^ ? ? ?[*+-]( +| )/, "");
|
||||||
|
nnl++;
|
||||||
|
nblock[nnl] = "ul";
|
||||||
|
newli = 1;
|
||||||
|
}
|
||||||
|
(nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?([0-9]+\.)+( +| )/ {
|
||||||
|
sub(/^ ? ? ?([0-9]+\.)+( +| )/, "");
|
||||||
|
nnl++;
|
||||||
|
nblock[nnl] = "ol";
|
||||||
|
newli = 1;
|
||||||
|
}
|
||||||
|
newli {
|
||||||
|
if(blank && nnl == nl && !par)
|
||||||
|
par = "p";
|
||||||
|
blank = 0;
|
||||||
|
printp(par);
|
||||||
|
if(nnl == nl && block[nl] == nblock[nl])
|
||||||
|
oprint("</li><li>");
|
||||||
|
}
|
||||||
|
blank && ! /^$/ {
|
||||||
|
if(match(block[nnl], /[ou]l/) && !par)
|
||||||
|
par = "p";
|
||||||
|
printp(par);
|
||||||
|
par = "p";
|
||||||
|
blank = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Close old blocks and open new ones
|
||||||
|
nnl != nl || nblock[nl] != block[nl] {
|
||||||
|
if(code){
|
||||||
|
oprint("</pre></code>");
|
||||||
|
code = 0;
|
||||||
|
}
|
||||||
|
printp(par);
|
||||||
|
b = (nnl > nl) ? nblock[nnl] : block[nnl];
|
||||||
|
par = (match(b, /[ou]l/)) ? "" : "p";
|
||||||
|
}
|
||||||
|
nnl < nl || (nnl == nl && nblock[nl] != block[nl]) {
|
||||||
|
for(; nl > nnl || (nnl == nl && pblock[nl] != block[nl]); nl--){
|
||||||
|
if(match(block[nl], /[ou]l/))
|
||||||
|
oprint("</li>");
|
||||||
|
oprint("</" block[nl] ">");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nnl > nl {
|
||||||
|
for(; nl < nnl; nl++){
|
||||||
|
block[nl + 1] = nblock[nl + 1];
|
||||||
|
oprint("<" block[nl + 1] ">");
|
||||||
|
if(match(block[nl + 1], /[ou]l/))
|
||||||
|
oprint("<li>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
oprint("<hr>");
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Code blocks
|
||||||
|
code && /^$/ {
|
||||||
|
if(blanK)
|
||||||
|
oprint("");
|
||||||
|
blank = 1;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
!text && sub(/^( | )/, "") {
|
||||||
|
if(blanK)
|
||||||
|
oprint("");
|
||||||
|
blank = 0;
|
||||||
|
if(!code)
|
||||||
|
oprint("<code><pre>");
|
||||||
|
code = 1;
|
||||||
|
$0 = eschtml($0);
|
||||||
|
oprint($0);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
oprint("</pre></code>");
|
||||||
|
code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Setex-style Headers
|
||||||
|
text && /^=+$/ {printp("h1"); next;}
|
||||||
|
text && /^-+$/ {printp("h2"); next;}
|
||||||
|
|
||||||
|
# Atx-Style headers
|
||||||
|
/^#+/ && (!newli || par=="p" || /^##/) {
|
||||||
|
for(n = 0; n < 6 && sub(/^# */, ""); n++)
|
||||||
|
sub(/#$/, "");
|
||||||
|
par = "h" n;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Paragraph
|
||||||
|
/^$/ {
|
||||||
|
printp(par);
|
||||||
|
par = "p";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add text
|
||||||
|
{ text = (text ? text " " : "") $0; }
|
||||||
|
|
||||||
|
END {
|
||||||
|
if(code){
|
||||||
|
oprint("</pre></code>");
|
||||||
|
code = 0;
|
||||||
|
}
|
||||||
|
printp(par);
|
||||||
|
for(; nl > 0; nl--){
|
||||||
|
if(match(block[nl], /[ou]l/))
|
||||||
|
oprint("</li>");
|
||||||
|
oprint("</" block[nl] ">");
|
||||||
|
}
|
||||||
|
gsub(/<<[^\"]*/, "", otext);
|
||||||
|
print(otext);
|
||||||
|
}
|
6
werc/bin/contrib/rc-httpd/handlers/authorize
Executable file
6
werc/bin/contrib/rc-httpd/handlers/authorize
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/rc
|
||||||
|
if(~ $REMOTE_USER ''){
|
||||||
|
extra_headers=($extra_headers 'WWW-Authenticate: Basic realm="'$"SERVER_NAME'"')
|
||||||
|
error 401
|
||||||
|
exit
|
||||||
|
}
|
46
werc/bin/contrib/rc-httpd/handlers/cgi
Executable file
46
werc/bin/contrib/rc-httpd/handlers/cgi
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/rc
|
||||||
|
fn filter_headers{
|
||||||
|
response=(200 OK)
|
||||||
|
lines=''
|
||||||
|
done=false
|
||||||
|
while(~ $done false){
|
||||||
|
line=`{getline}
|
||||||
|
head=`{echo $line | awk '{print tolower($1)}'}
|
||||||
|
if(~ $head status:*)
|
||||||
|
response=`{echo $line | awk '{$1="" ; print}'}
|
||||||
|
if not if(~ $line '')
|
||||||
|
done=true
|
||||||
|
if not
|
||||||
|
lines=$"lines^$"line^$cr^'
|
||||||
|
'
|
||||||
|
}
|
||||||
|
echo 'HTTP/1.1' $"response^$cr
|
||||||
|
echo -n $"lines
|
||||||
|
do_log $response(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_cgi {
|
||||||
|
path=$cgi_path exec $"cgi_bin $params || echo 'Status: 500'
|
||||||
|
}
|
||||||
|
|
||||||
|
cgi_bin=$1
|
||||||
|
cgi_dir=.
|
||||||
|
if(! ~ $#* 1)
|
||||||
|
cgi_dir=$*($#*)
|
||||||
|
if not if(~ $"cgi_bin /*){
|
||||||
|
cgi_dir=`{basename -d $"cgi_bin}
|
||||||
|
cgi_dir=$"cgi_dir
|
||||||
|
}
|
||||||
|
if(! ~ $"cgi_bin */*)
|
||||||
|
cgi_bin=./$"cgi_bin
|
||||||
|
if(! builtin cd $"cgi_dir >[2]/dev/null || ! test -x $"cgi_bin){
|
||||||
|
error 500
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
run_cgi | {
|
||||||
|
filter_headers
|
||||||
|
emit_extra_headers
|
||||||
|
echo $cr
|
||||||
|
exec cat
|
||||||
|
}
|
111
werc/bin/contrib/rc-httpd/handlers/dir-index
Executable file
111
werc/bin/contrib/rc-httpd/handlers/dir-index
Executable file
|
@ -0,0 +1,111 @@
|
||||||
|
#!/bin/rc
|
||||||
|
PATH_INFO=`{echo $PATH_INFO | urldecode.awk}
|
||||||
|
full_path=$"FS_ROOT^$"PATH_INFO
|
||||||
|
full_path=$"full_path
|
||||||
|
if(! test -d $full_path){
|
||||||
|
error 404
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if(! test -r $full_path -x $full_path){
|
||||||
|
error 503
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
do_log 200
|
||||||
|
builtin cd $full_path
|
||||||
|
if(~ $"NOINDEXFILE ^ $"NOINDEX ''){
|
||||||
|
ifile=index.htm*
|
||||||
|
if(! ~ $ifile(1) *'*'){
|
||||||
|
PATH_INFO=$ifile(1)
|
||||||
|
FS_ROOT=''
|
||||||
|
exec serve-static
|
||||||
|
}
|
||||||
|
}
|
||||||
|
title=`{echo $SITE_TITLE | sed s,%s,^$"PATH_INFO^,}
|
||||||
|
title=$"title
|
||||||
|
lso=()
|
||||||
|
switch($2){
|
||||||
|
case size
|
||||||
|
# ls has no option to sort by size
|
||||||
|
# could pipe it through sort, I suppose
|
||||||
|
case date
|
||||||
|
lso=-t
|
||||||
|
}
|
||||||
|
echo 'HTTP/1.1 200 OK'^$cr
|
||||||
|
emit_extra_headers
|
||||||
|
echo 'Content-type: text/html'^$cr
|
||||||
|
echo $cr
|
||||||
|
echo '<html>
|
||||||
|
<head>
|
||||||
|
<title>'^$title^'</title>
|
||||||
|
<style type="text/css">
|
||||||
|
.size {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 4pt;
|
||||||
|
}
|
||||||
|
.day {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 3pt;
|
||||||
|
}
|
||||||
|
.datetime {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
text-align: right;
|
||||||
|
padding-left: 3pt;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>'
|
||||||
|
echo '<h1>'^$title^'</h1>'
|
||||||
|
if(! ~ $PATH_INFO /)
|
||||||
|
echo '<a href="../">Parent directory</a>'
|
||||||
|
echo '<table>'
|
||||||
|
ls -lQ $lso | awk '
|
||||||
|
function urlencode(loc){
|
||||||
|
# very minimal encoding, just enough for our static-file purposes
|
||||||
|
url=loc
|
||||||
|
gsub("%", "%25", url) # this one first!
|
||||||
|
gsub("\\$", "%24", url)
|
||||||
|
gsub("&", "%26", url)
|
||||||
|
gsub("\\+", "%2B", url)
|
||||||
|
gsub("\\?", "%3F", url)
|
||||||
|
gsub(" ", "%20", url)
|
||||||
|
gsub("\"", "%22", url)
|
||||||
|
gsub("#", "%23", url)
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
function hrsize(size){
|
||||||
|
if(size > 1073741824) return sprintf("%.1fGB", size/1073741824)
|
||||||
|
if(size > 10485760) return sprintf("%iMB", size/1048576)
|
||||||
|
if(size > 1048576) return sprintf("%.1fMB", size/1048576)
|
||||||
|
if(size > 10240) return sprintf("%iKB", size/1024)
|
||||||
|
if(size > 1024) return sprintf("%.1fKB", size/1024)
|
||||||
|
return sprintf("%iB", size)
|
||||||
|
}
|
||||||
|
/^(-|a)/ {
|
||||||
|
print "<tr>"
|
||||||
|
print "<td class=\"size\">"hrsize($6)"</td>"
|
||||||
|
print "<td class=\"month\">"$7"</td>"
|
||||||
|
print "<td class=\"day\">"$8"</td>"
|
||||||
|
print "<td class=\"datetime\">"$9"</td>"
|
||||||
|
$1="" ; $2="" ; $3="" ; $4="" ; $5="" ; $6="" ; $7="" ; $8="" ; $9=""
|
||||||
|
sub("^ *?", "")
|
||||||
|
print "<td><a class=\"file name\" href=\""urlencode($0)"\">"$0"</a></td>"
|
||||||
|
print "</tr>"
|
||||||
|
$0=""
|
||||||
|
}
|
||||||
|
/^d/ {
|
||||||
|
print "<tr>"
|
||||||
|
print "<td class=\"size\"> </td>"
|
||||||
|
print "<td class=\"month\">"$7"</td>"
|
||||||
|
print "<td class=\"day\">"$8"</td>"
|
||||||
|
print "<td class=\"datetime\">"$9"</td>"
|
||||||
|
$1="" ; $2="" ; $3="" ; $4="" ; $5="" ; $6="" ; $7="" ; $8="" ; $9=""
|
||||||
|
sub("^ *?", "")
|
||||||
|
print "<td><a class=\"dir name\" href=\""urlencode($0)"/\">"$0"/</a></td>"
|
||||||
|
print "</tr>"
|
||||||
|
}'
|
||||||
|
echo '</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>'
|
43
werc/bin/contrib/rc-httpd/handlers/error
Executable file
43
werc/bin/contrib/rc-httpd/handlers/error
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/rc
|
||||||
|
# DO NOT make this script callable directly from the web!
|
||||||
|
fn do_error{
|
||||||
|
echo 'HTTP/1.1 '^$1^$cr
|
||||||
|
emit_extra_headers
|
||||||
|
echo 'Content-type: text/html'^$cr
|
||||||
|
echo $cr
|
||||||
|
echo '<html>
|
||||||
|
<head>
|
||||||
|
<title>'^$1^'</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>'^$1^'</h1>'
|
||||||
|
echo $2
|
||||||
|
echo '<p><i>rc-httpd at' $SERVER_NAME '</i>'
|
||||||
|
echo '
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn 401{
|
||||||
|
do_error '401 Unauthorized' \
|
||||||
|
'The requested path '^$"location^' requires authorization.'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn 404{
|
||||||
|
do_error '404 Not Found' \
|
||||||
|
'The requested path '^$"location^' was not found on this server.'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn 500{
|
||||||
|
do_error '500 Internal Server Error' \
|
||||||
|
'The server has encountered an internal misconfiguration and is unable to satisfy your request.'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn 503{
|
||||||
|
do_error '503 Forbidden' \
|
||||||
|
'You do not have permission to access '^$"location^' on this server.'
|
||||||
|
}
|
||||||
|
|
||||||
|
do_log $1
|
||||||
|
$1
|
30
werc/bin/contrib/rc-httpd/handlers/redirect
Executable file
30
werc/bin/contrib/rc-httpd/handlers/redirect
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/rc
|
||||||
|
if(~ $#2 0){
|
||||||
|
error 500
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
switch($1){
|
||||||
|
case perm*
|
||||||
|
do_log 301
|
||||||
|
echo 'HTTP/1.1 301 Moved Permanently'^$cr
|
||||||
|
case temp*
|
||||||
|
do_log 302
|
||||||
|
echo 'HTTP/1.1 302 Moved Temporarily'^$cr
|
||||||
|
case seeother
|
||||||
|
do_log 303
|
||||||
|
echo 'HTTP/1.1 303 See Other'^$cr
|
||||||
|
case *
|
||||||
|
error 500
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
echo 'Location: ' ^ $2 ^ $cr
|
||||||
|
emit_extra_headers
|
||||||
|
echo 'Content-type: text/html'^$cr
|
||||||
|
echo $cr
|
||||||
|
echo '<html><body>'
|
||||||
|
if(~ $#3 0)
|
||||||
|
echo 'Browser did not accept redirect.'
|
||||||
|
if not
|
||||||
|
echo $3
|
||||||
|
echo '<a href="'^$"location^'/">Click here</a>'
|
||||||
|
echo '</body></html>'
|
43
werc/bin/contrib/rc-httpd/handlers/serve-static
Executable file
43
werc/bin/contrib/rc-httpd/handlers/serve-static
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/rc
|
||||||
|
full_path=`{echo $"FS_ROOT^$"PATH_INFO | urldecode.awk}
|
||||||
|
full_path=$"full_path
|
||||||
|
if(~ $full_path */)
|
||||||
|
error 503
|
||||||
|
if(test -d $full_path){
|
||||||
|
redirect perm $"location^'/' \
|
||||||
|
'URL not quite right, and browser did not accept redirect.'
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if(! test -e $full_path){
|
||||||
|
error 404
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if(! test -r $full_path){
|
||||||
|
error 503
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
do_log 200
|
||||||
|
switch($full_path){
|
||||||
|
case *.html *.htm
|
||||||
|
type=text/html
|
||||||
|
case *.css
|
||||||
|
type=text/css
|
||||||
|
case *.txt
|
||||||
|
type='text/plain; charset=utf-8'
|
||||||
|
case *.jpg *.jpeg
|
||||||
|
type=image/jpeg
|
||||||
|
case *.gif
|
||||||
|
type=image/gif
|
||||||
|
case *.png
|
||||||
|
type=image/png
|
||||||
|
case *
|
||||||
|
type=`{file -m $full_path || file -i $full_path} # GROSS
|
||||||
|
}
|
||||||
|
max_age=3600 # 1 hour
|
||||||
|
echo 'HTTP/1.1 200 OK'^$cr
|
||||||
|
emit_extra_headers
|
||||||
|
echo 'Content-type: '^$type^'; charset=utf-8'^$cr
|
||||||
|
echo 'Content-length: '^`{ls -l $full_path | awk '{print $6}'}
|
||||||
|
echo 'Cache-control: max-age='^$max_age^$cr
|
||||||
|
echo $cr
|
||||||
|
exec cat $full_path
|
14
werc/bin/contrib/rc-httpd/handlers/static-or-cgi
Executable file
14
werc/bin/contrib/rc-httpd/handlers/static-or-cgi
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/rc
|
||||||
|
cgiargs=$*
|
||||||
|
|
||||||
|
fn error{
|
||||||
|
if(~ $1 404)
|
||||||
|
exec cgi $cgiargs
|
||||||
|
if not
|
||||||
|
$rc_httpd_dir/handlers/error $1
|
||||||
|
}
|
||||||
|
|
||||||
|
if(~ $location */)
|
||||||
|
exec cgi $cgiargs
|
||||||
|
if not
|
||||||
|
exec serve-static
|
5
werc/bin/contrib/rc-httpd/handlers/static-or-index
Executable file
5
werc/bin/contrib/rc-httpd/handlers/static-or-index
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/rc
|
||||||
|
if(~ $PATH_INFO */)
|
||||||
|
exec dir-index $params
|
||||||
|
if not
|
||||||
|
exec serve-static
|
39
werc/bin/contrib/rc-httpd/lib/urldecode.awk
Executable file
39
werc/bin/contrib/rc-httpd/lib/urldecode.awk
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
# taken from werc
|
||||||
|
BEGIN {
|
||||||
|
hextab ["0"] = 0; hextab ["8"] = 8;
|
||||||
|
hextab ["1"] = 1; hextab ["9"] = 9;
|
||||||
|
hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10
|
||||||
|
hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11;
|
||||||
|
hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12;
|
||||||
|
hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13;
|
||||||
|
hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14;
|
||||||
|
hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
decoded = ""
|
||||||
|
i = 1
|
||||||
|
len = length ($0)
|
||||||
|
while ( i <= len ) {
|
||||||
|
c = substr ($0, i, 1)
|
||||||
|
if ( c == "%" ) {
|
||||||
|
if ( i+2 <= len ) {
|
||||||
|
c1 = substr ($0, i+1, 1)
|
||||||
|
c2 = substr ($0, i+2, 1)
|
||||||
|
if ( hextab [c1] == "" || hextab [c2] == "" ) {
|
||||||
|
print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2"
|
||||||
|
} else {
|
||||||
|
code = 0 + hextab [c1] * 16 + hextab [c2] + 0
|
||||||
|
c = sprintf ("%c", code)
|
||||||
|
i = i + 2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print "WARNING: invalid % encoding: " substr ($0, i, len - i)
|
||||||
|
}
|
||||||
|
} else if ( c == "+" ) {
|
||||||
|
c = " "
|
||||||
|
}
|
||||||
|
decoded = decoded c
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
printf "%s", decoded
|
||||||
|
}
|
106
werc/bin/contrib/rc-httpd/rc-httpd
Executable file
106
werc/bin/contrib/rc-httpd/rc-httpd
Executable file
|
@ -0,0 +1,106 @@
|
||||||
|
#!/bin/rc
|
||||||
|
rc_httpd_dir=/werc/bin/contrib/rc-httpd
|
||||||
|
path=($PLAN9/bin $rc_httpd_dir/handlers $PATH)
|
||||||
|
cgi_path=$PLAN9/bin
|
||||||
|
SERVER_PORT=80 # default for CGI scripts, may be overridden by the Host header
|
||||||
|
extra_headers='Server: rc-httpd'
|
||||||
|
cr=
|
||||||
|
|
||||||
|
fn do_log{
|
||||||
|
echo `{date} :: $SERVER_NAME :: $request :: \
|
||||||
|
$HTTP_USER_AGENT :: $1 :: $HTTP_REFERER >[1=2]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_extra_headers{
|
||||||
|
for(header in $extra_headers)
|
||||||
|
echo $"header^$cr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getline{ read | sed 's/'^$"cr^'$//g' }
|
||||||
|
|
||||||
|
fn terminate{
|
||||||
|
echo `{date} connection terminated >[1=2]
|
||||||
|
exit terminate
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trim_input{ read -c $CONTENT_LENGTH }
|
||||||
|
|
||||||
|
request=`{getline}
|
||||||
|
if(~ $#request 0)
|
||||||
|
terminate
|
||||||
|
REQUEST_METHOD=$request(1)
|
||||||
|
REQUEST_URI=$request(2)
|
||||||
|
reqlines=''
|
||||||
|
HTTP_COOKIE=''
|
||||||
|
REMOTE_USER=''
|
||||||
|
done=false
|
||||||
|
chunked=no
|
||||||
|
while(~ $"done false){
|
||||||
|
line=`{getline}
|
||||||
|
if(~ $#line 0)
|
||||||
|
done=true
|
||||||
|
reqlines=$"reqlines$"line'
|
||||||
|
'
|
||||||
|
h=`{echo $line | awk '{print tolower($1)}'}
|
||||||
|
switch($h){
|
||||||
|
case ''
|
||||||
|
done=true
|
||||||
|
case host:
|
||||||
|
SERVER_NAME=$line(2)
|
||||||
|
case referer:
|
||||||
|
HTTP_REFERER=$line(2)
|
||||||
|
case user-agent:
|
||||||
|
HTTP_USER_AGENT=`{echo $line | sed 's;[^:]+:[ ]+;;'}
|
||||||
|
case content-length:
|
||||||
|
CONTENT_LENGTH=$line(2)
|
||||||
|
case content-type:
|
||||||
|
CONTENT_TYPE=$line(2)
|
||||||
|
case cookie:
|
||||||
|
cookie=`{echo $line | sed 's;^[^:]+:[ ]*;;'}
|
||||||
|
HTTP_COOKIE=$"HTTP_COOKIE^$"cookie^'; '
|
||||||
|
case authorization:
|
||||||
|
REMOTE_USER=`{auth/httpauth $line(3)}
|
||||||
|
case transfer-encoding:
|
||||||
|
~ $line(2) chunked && chunked=yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(~ $REQUEST_URI *://* //*){
|
||||||
|
SERVER_NAME=`{echo $REQUEST_URI | sed '
|
||||||
|
s;^[^:]+:;;
|
||||||
|
s;^//([^/]+).*;\1;'}
|
||||||
|
REQUEST_URI=`{echo $REQUEST_URI | sed '
|
||||||
|
s;^[^:]+:;;
|
||||||
|
s;^//[^/]+/?;/;'}
|
||||||
|
}
|
||||||
|
QUERY_STRING=`{echo $REQUEST_URI | sed 's;[^?]*\??;;'}
|
||||||
|
params=`{echo $QUERY_STRING | sed 's;\+; ;g'}
|
||||||
|
location=`{echo $REQUEST_URI | sed '
|
||||||
|
s;\?.*;;
|
||||||
|
s;[^/]+/\.\./;/;g
|
||||||
|
s;/\./;/;g
|
||||||
|
s;//+;/;g
|
||||||
|
'}
|
||||||
|
SERVER_NAME=`{echo $SERVER_NAME | sed 's;^(\[[^\]]+\]|[^:]+)\:([0-9]+)$;\1 \2;'}
|
||||||
|
if(~ $#SERVER_NAME 2){
|
||||||
|
SERVER_PORT=$SERVER_NAME(2)
|
||||||
|
SERVER_NAME=$SERVER_NAME(1)
|
||||||
|
}
|
||||||
|
switch($SERVER_NAME){
|
||||||
|
case */* ..
|
||||||
|
error 400
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if(~ $REQUEST_METHOD (PUT POST)){
|
||||||
|
if(! ~ $"CONTENT_LENGTH '')
|
||||||
|
trim_input | exec $rc_httpd_dir/select-handler
|
||||||
|
if not{
|
||||||
|
if(~ $chunked yes){
|
||||||
|
echo 'HTTP/1.1 411 Length required'^$cr
|
||||||
|
echo $cr
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
exec $rc_httpd_dir/select-handler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
. $rc_httpd_dir/select-handler
|
20
werc/bin/contrib/rc-httpd/select-handler
Executable file
20
werc/bin/contrib/rc-httpd/select-handler
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/rc
|
||||||
|
rfork n
|
||||||
|
|
||||||
|
# Route requests to werc.
|
||||||
|
# Change paths to match your system.
|
||||||
|
|
||||||
|
if(~ $SERVER_NAME 9base.werc.cat-v.org)
|
||||||
|
PLAN9=/usr/local/9base
|
||||||
|
if(~ $SERVER_NAME frontbase.werc.cat-v.org)
|
||||||
|
PLAN9=/usr/local/plan9front
|
||||||
|
if(~ $SERVER_NAME plan9port.werc.cat-v.org)
|
||||||
|
PLAN9=/usr/local/plan9
|
||||||
|
|
||||||
|
if(~ $SERVER_NAME *){
|
||||||
|
PATH_INFO=$location
|
||||||
|
FS_ROOT=/werc/sites/$SERVER_NAME
|
||||||
|
exec static-or-cgi /werc/bin/werc.rc
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
error 503
|
7
werc/bin/contrib/tcp80
Executable file
7
werc/bin/contrib/tcp80
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/rc
|
||||||
|
# For use with listen(8).
|
||||||
|
# Change paths to match your system.
|
||||||
|
# Eitdit rc-httpd/rc-httpd to match your system.
|
||||||
|
PLAN9=/usr/local/plan9
|
||||||
|
PATH=($PATH /home/sl/www/werc/bin/contrib)
|
||||||
|
exec /home/sl/www/werc/bin/contrib/rc-httpd/rc-httpd >>[2]/var/log/rc-httpd
|
39
werc/bin/contrib/urldecode.awk
Executable file
39
werc/bin/contrib/urldecode.awk
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/awk -f
|
||||||
|
BEGIN {
|
||||||
|
hextab ["0"] = 0; hextab ["8"] = 8;
|
||||||
|
hextab ["1"] = 1; hextab ["9"] = 9;
|
||||||
|
hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10
|
||||||
|
hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11;
|
||||||
|
hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12;
|
||||||
|
hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13;
|
||||||
|
hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14;
|
||||||
|
hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
decoded = ""
|
||||||
|
i = 1
|
||||||
|
len = length ($0)
|
||||||
|
while ( i <= len ) {
|
||||||
|
c = substr ($0, i, 1)
|
||||||
|
if ( c == "%" ) {
|
||||||
|
if ( i+2 <= len ) {
|
||||||
|
c1 = substr ($0, i+1, 1)
|
||||||
|
c2 = substr ($0, i+2, 1)
|
||||||
|
if ( hextab [c1] == "" || hextab [c2] == "" ) {
|
||||||
|
print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2"
|
||||||
|
} else {
|
||||||
|
code = 0 + hextab [c1] * 16 + hextab [c2] + 0
|
||||||
|
c = sprintf ("%c", code)
|
||||||
|
i = i + 2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print "WARNING: invalid % encoding: " substr ($0, i, len - i)
|
||||||
|
}
|
||||||
|
} else if ( c == "+" ) {
|
||||||
|
c = " "
|
||||||
|
}
|
||||||
|
decoded = decoded c
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
print decoded
|
||||||
|
}
|
126
werc/bin/contrib/urlencode.awk
Executable file
126
werc/bin/contrib/urlencode.awk
Executable file
|
@ -0,0 +1,126 @@
|
||||||
|
# Taken from http://www.shelldorado.com/scripts/cmds/urlencode
|
||||||
|
##########################################################################
|
||||||
|
# Title : urlencode - encode URL data
|
||||||
|
# Author : Heiner Steven (heiner.steven@odn.de)
|
||||||
|
# Date : 2000-03-15
|
||||||
|
# Requires : awk
|
||||||
|
# Categories : File Conversion, WWW, CGI
|
||||||
|
# SCCS-Id. : @(#) urlencode 1.4 06/10/29
|
||||||
|
##########################################################################
|
||||||
|
# Description
|
||||||
|
# Encode data according to
|
||||||
|
# RFC 1738: "Uniform Resource Locators (URL)" and
|
||||||
|
# RFC 1866: "Hypertext Markup Language - 2.0" (HTML)
|
||||||
|
#
|
||||||
|
# This encoding is used i.e. for the MIME type
|
||||||
|
# "application/x-www-form-urlencoded"
|
||||||
|
#
|
||||||
|
# Notes
|
||||||
|
# o The default behaviour is not to encode the line endings. This
|
||||||
|
# may not be what was intended, because the result will be
|
||||||
|
# multiple lines of output (which cannot be used in an URL or a
|
||||||
|
# HTTP "POST" request). If the desired output should be one
|
||||||
|
# line, use the "-l" option.
|
||||||
|
#
|
||||||
|
# o The "-l" option assumes, that the end-of-line is denoted by
|
||||||
|
# the character LF (ASCII 10). This is not true for Windows or
|
||||||
|
# Mac systems, where the end of a line is denoted by the two
|
||||||
|
# characters CR LF (ASCII 13 10).
|
||||||
|
# We use this for symmetry; data processed in the following way:
|
||||||
|
# cat | urlencode -l | urldecode -l
|
||||||
|
# should (and will) result in the original data
|
||||||
|
#
|
||||||
|
# o Large lines (or binary files) will break many AWK
|
||||||
|
# implementations. If you get the message
|
||||||
|
# awk: record `...' too long
|
||||||
|
# record number xxx
|
||||||
|
# consider using GNU AWK (gawk).
|
||||||
|
#
|
||||||
|
# o urlencode will always terminate it's output with an EOL
|
||||||
|
# character
|
||||||
|
#
|
||||||
|
# Thanks to Stefan Brozinski for pointing out a bug related to non-standard
|
||||||
|
# locales.
|
||||||
|
#
|
||||||
|
# See also
|
||||||
|
# urldecode
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
PN=`basename "$0"` # Program name
|
||||||
|
VER='1.4'
|
||||||
|
|
||||||
|
: ${AWK=awk}
|
||||||
|
|
||||||
|
Usage () {
|
||||||
|
echo >&2 "$PN - encode URL data, $VER
|
||||||
|
usage: $PN [-l] [file ...]
|
||||||
|
-l: encode line endings (result will be one line of output)
|
||||||
|
|
||||||
|
The default is to encode each input line on its own."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Msg () {
|
||||||
|
for MsgLine
|
||||||
|
do echo "$PN: $MsgLine" >&2
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
Fatal () { Msg "$@"; exit 1; }
|
||||||
|
|
||||||
|
set -- `getopt hl "$@" 2>/dev/null` || Usage
|
||||||
|
[ $# -lt 1 ] && Usage # "getopt" detected an error
|
||||||
|
|
||||||
|
EncodeEOL=no
|
||||||
|
while [ $# -gt 0 ]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-l) EncodeEOL=yes;;
|
||||||
|
--) shift; break;;
|
||||||
|
-h) Usage;;
|
||||||
|
-*) Usage;;
|
||||||
|
*) break;; # First file name
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
LANG=C export LANG
|
||||||
|
$AWK '
|
||||||
|
BEGIN {
|
||||||
|
# We assume an awk implementation that is just plain dumb.
|
||||||
|
# We will convert an character to its ASCII value with the
|
||||||
|
# table ord[], and produce two-digit hexadecimal output
|
||||||
|
# without the printf("%02X") feature.
|
||||||
|
|
||||||
|
EOL = "%0A" # "end of line" string (encoded)
|
||||||
|
split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ")
|
||||||
|
hextab [0] = 0
|
||||||
|
for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
|
||||||
|
if ("'"$EncodeEOL"'" == "yes") EncodeEOL = 1; else EncodeEOL = 0
|
||||||
|
}
|
||||||
|
{
|
||||||
|
encoded = ""
|
||||||
|
for ( i=1; i<=length ($0); ++i ) {
|
||||||
|
c = substr ($0, i, 1)
|
||||||
|
if ( c ~ /[a-zA-Z0-9.-]/ ) {
|
||||||
|
encoded = encoded c # safe character
|
||||||
|
} else if ( c == " " ) {
|
||||||
|
encoded = encoded "+" # special handling
|
||||||
|
} else {
|
||||||
|
# unsafe character, encode it as a two-digit hex-number
|
||||||
|
lo = ord [c] % 16
|
||||||
|
hi = int (ord [c] / 16);
|
||||||
|
encoded = encoded "%" hextab [hi] hextab [lo]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( EncodeEOL ) {
|
||||||
|
printf ("%s", encoded EOL)
|
||||||
|
} else {
|
||||||
|
print encoded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
#if ( EncodeEOL ) print ""
|
||||||
|
}
|
||||||
|
' "$@"
|
||||||
|
|
30
werc/bin/contrib/webserver.rc
Executable file
30
werc/bin/contrib/webserver.rc
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/rc
|
||||||
|
|
||||||
|
# A web server in rc by maht
|
||||||
|
# Originally from http://www.proweb.co.uk/~matt/rc/webserver.rc
|
||||||
|
|
||||||
|
ifs=' '
|
||||||
|
request=`{sed 1q}
|
||||||
|
|
||||||
|
url=$request(2)
|
||||||
|
file=`{echo $url | sed 's/http:\/\/[^\/]*//' | tr -d \012}
|
||||||
|
|
||||||
|
if(test -d $file){
|
||||||
|
file=$file ^'/index.html'
|
||||||
|
}
|
||||||
|
if(test -e $file) {
|
||||||
|
response='200'
|
||||||
|
}
|
||||||
|
if not {
|
||||||
|
response='404'
|
||||||
|
file='404.html'
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'HTTP/1.1 ' ^$response
|
||||||
|
echo 'Date: ' `{date}
|
||||||
|
echo 'Server: rc shell'
|
||||||
|
echo 'Content-Length: ' `{cat $file | wc -c | tr -d ' '}
|
||||||
|
echo 'Content-Type: ' `{file -i $file | awk '{ print $2 }'}
|
||||||
|
echo 'Connection: close'
|
||||||
|
echo
|
||||||
|
cat $file
|
152
werc/bin/corehandlers.rc
Executable file
152
werc/bin/corehandlers.rc
Executable file
|
@ -0,0 +1,152 @@
|
||||||
|
# Werc builtin handlers
|
||||||
|
|
||||||
|
fn nav_tree {
|
||||||
|
if(! ~ $#sideBarNavTitle 0)
|
||||||
|
echo '<p class="sideBarTitle">'$"sideBarNavTitle':</p>'
|
||||||
|
# Ignore stderr, last path element might be a file that doesn't exist (eg., foo for foo.md)
|
||||||
|
# /./ to deal with p9p's ls failure to follow dir symlinks otherwise
|
||||||
|
ls -F $sitedir/./$req_paths_list >[2]/dev/null \
|
||||||
|
| {
|
||||||
|
sed $dirfilter'/\/[^_.\/][^\/]*(\.(md|txt|html)|\/)$/!d; s!^'$sitedir'!!; '$dirclean
|
||||||
|
if(! ~ $#synth_paths 0) echo $synth_paths | tr ' ' $NEW_LINE
|
||||||
|
} | sort -u | awk -F/ '
|
||||||
|
function p(x, y, s) { for(i=0; i < x-y; i+=1) print s }
|
||||||
|
BEGIN { lNF=2; print "<ul>" }
|
||||||
|
{
|
||||||
|
d = ""
|
||||||
|
if(match($0, "/$"))
|
||||||
|
d = "/"
|
||||||
|
sub("/$", "") # Strip trailing / for dirs so NF is consistent
|
||||||
|
|
||||||
|
p(NF, lNF, "<li><ul>")
|
||||||
|
p(lNF, NF, "</ul></li>")
|
||||||
|
lNF = NF
|
||||||
|
|
||||||
|
bname = $NF d
|
||||||
|
path = $0 d
|
||||||
|
gsub(/[\-_]/, " ", bname)
|
||||||
|
|
||||||
|
# To avoid false matches add trailing / even for plain files to act as delimiter
|
||||||
|
pa = path
|
||||||
|
gsub(/[^\/]$/, "&/", pa)
|
||||||
|
|
||||||
|
if(index(ENVIRON["req_path"] "/", pa) == 1)
|
||||||
|
print "<li><a href=\"" path "\" class=\"thisPage\">»<i> " bname "</i></a></li>"
|
||||||
|
else
|
||||||
|
print "<li><a href=\"" path "\">› " bname "</a></li>"
|
||||||
|
}
|
||||||
|
END { p(lNF, 2, "</ul></li>"); print "</ul>" }'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link_bar {
|
||||||
|
if(~ $1 -t) {
|
||||||
|
echo '<p class="sideBarTitle">'$2'</p>'
|
||||||
|
shift; shift
|
||||||
|
}
|
||||||
|
echo '<ul>'
|
||||||
|
while(! ~ $#* 0) {
|
||||||
|
echo '<li><a href="'$2'">- '$1'</a></li>'
|
||||||
|
shift; shift
|
||||||
|
}
|
||||||
|
echo '</ul>'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn md_handler { $formatter $1 }
|
||||||
|
|
||||||
|
fn tpl_handler { template $* }
|
||||||
|
|
||||||
|
fn html_handler {
|
||||||
|
# body states: 0 = no <body> found, 2 = after <body>, 1 = after <body></body>, -1 = after </body>
|
||||||
|
awk 'gsub(".*<[Bb][Oo][Dd][Yy][^>]*>", "") > 0 {body=2}
|
||||||
|
gsub("</ *[Bb][Oo][Dd][Yy][^>]*>.*", "") > 0 {print; body=body-1}
|
||||||
|
body==2 {print}
|
||||||
|
body==0 {buf=buf "\n" $0}
|
||||||
|
END {if(body<=0) {print buf}}' < $1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn txt_handler {
|
||||||
|
# Note: Words are not broken, even if they are way beyond 82 chars long
|
||||||
|
echo '<pre>'
|
||||||
|
sed 's/</\</g; s/>/\>/g' < $1 | fmt -l 82 -j
|
||||||
|
echo '</pre>'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dir_listing_handler {
|
||||||
|
d=`{basename -d $1}
|
||||||
|
if(~ $#d 0)
|
||||||
|
d='/'
|
||||||
|
echo $d|sed 's,.*//,,g; s,/$,,; s,/, / ,g; s,.*,<h1 class="dir-list-head">&</h1> <ul class="dir-list">,'
|
||||||
|
# Symlinks suck: '/.' forces ls to list the linked dir if $d is a symlink.
|
||||||
|
ls -F $dir_listing_ls_opts $sitedir$d/. | sed $dirfilter$dirclean' s,.*/([^/]+/?)$,<li><a href="\1">\1</a></li>,'
|
||||||
|
echo '</ul>'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notices_handler {
|
||||||
|
for(type in notify_errors notify_notes notify_success)
|
||||||
|
for(n in $$type)
|
||||||
|
echo '<div class="'$type'"><b>'$"n'</b></div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_handlers {
|
||||||
|
|
||||||
|
if(test -f $local_path.md) {
|
||||||
|
local_file=$local_path.md
|
||||||
|
handler_body_main=(md_handler $local_file)
|
||||||
|
}
|
||||||
|
if not if(test -f $local_path.tpl) {
|
||||||
|
local_file=$local_path.tpl
|
||||||
|
handler_body_main=(tpl_handler $local_file)
|
||||||
|
}
|
||||||
|
if not if(test -f $local_path.html) {
|
||||||
|
local_file=$local_path.html
|
||||||
|
handler_body_main=(html_handler $local_file)
|
||||||
|
}
|
||||||
|
# Global tpl (eg sitemap.tpl), should take precedence over txt handler!
|
||||||
|
if not if(test -f tpl^$req_path^.tpl)
|
||||||
|
# XXX Should we set $local_file for global .tpls?
|
||||||
|
handler_body_main=(tpl_handler tpl^$req_path^.tpl)
|
||||||
|
if not if(test -f $local_path.txt) {
|
||||||
|
local_file=$local_path.txt
|
||||||
|
handler_body_main=(txt_handler $local_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
# XXX Should check that $enabled_apps exist in $werc_apps?
|
||||||
|
# XXX Should split init of apps that provide main handler (eg., blog) and apps that don't (eg., comments)?
|
||||||
|
if(! ~ $#enabled_apps 0)
|
||||||
|
for(a in $enabled_apps)
|
||||||
|
$a^'_init'
|
||||||
|
|
||||||
|
if(! ~ $#handler_body_main 0)
|
||||||
|
{ } # We are done
|
||||||
|
# Dir listing
|
||||||
|
if not if(~ $local_path */index) {
|
||||||
|
handler_body_main=(dir_listing_handler $req_path)
|
||||||
|
if(test -f $sitedir$req_path'_header.md')
|
||||||
|
ll_add handlers_body_head md_handler $sitedir$req_path'_header.md'
|
||||||
|
if(test -f $sitedir$req_path'_footer.md')
|
||||||
|
ll_add handlers_body_foot md_handler $sitedir$req_path'_footer.md'
|
||||||
|
}
|
||||||
|
# Canonize explicit .html urls, the web server might handle this first!
|
||||||
|
if not if(~ $local_path *.html && test -f $local_path)
|
||||||
|
perm_redirect `{ echo $req_path|sed 's/.html$//' }
|
||||||
|
# Fallback static file handler
|
||||||
|
if not if(test -f $local_path)
|
||||||
|
static_file $local_path
|
||||||
|
if not if(~ $req_path /pub/* && test -f .$req_path)
|
||||||
|
static_file .$req_path
|
||||||
|
# File not found
|
||||||
|
if not
|
||||||
|
setup_404_handler
|
||||||
|
}
|
||||||
|
|
||||||
|
# This function allows config files to define their own 404 handlers.
|
||||||
|
fn setup_404_handler {
|
||||||
|
handler_body_main=(tpl_handler `{get_lib_file 404.tpl})
|
||||||
|
echo 'Status: 404 Not Found'
|
||||||
|
dprint 'NOT FOUND: '$SERVER_NAME^$"REQUEST_URI^' - '^$"HTTP_REFERER^' - '^$"HTTP_USER_AGENT
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_handlers { for(h in $*) run_handler $$h }
|
||||||
|
fn run_handler { $*(1) $*(2-) }
|
||||||
|
|
||||||
|
|
37
werc/bin/fltr_cache.rc
Executable file
37
werc/bin/fltr_cache.rc
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/rc
|
||||||
|
|
||||||
|
fn fltr_cache {
|
||||||
|
a=()
|
||||||
|
tmpf=()
|
||||||
|
|
||||||
|
proc=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
if(~ $#* 0) {
|
||||||
|
tmpf=/tmp/fmttmp.$pid
|
||||||
|
f=$tmpf
|
||||||
|
score=`{{tee $tmpf || exit 1} | sha1sum}
|
||||||
|
}
|
||||||
|
if not {
|
||||||
|
f=$1
|
||||||
|
if(~ $f */) {
|
||||||
|
score=`{du -an $f | sha1sum || exit 1} # XXX using -n(bytes) instead of -t(lastmod) because sitemap proc touches files in tree.
|
||||||
|
a=$f
|
||||||
|
f=/dev/null
|
||||||
|
}
|
||||||
|
if not {
|
||||||
|
score=`{sha1sum $f || exit 1}
|
||||||
|
score=$score(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cachedir=/tmp/fltr_cache/$score
|
||||||
|
mkdir -p $cachedir >[2]/dev/null
|
||||||
|
|
||||||
|
if(test -s $cachedir/$proc)
|
||||||
|
cat $cachedir/$proc
|
||||||
|
if not
|
||||||
|
if($proc $a < $f | tee $cachedir/$pid)
|
||||||
|
mv $cachedir/$pid $cachedir/$proc
|
||||||
|
|
||||||
|
rm $tmpf $cachedir/$pid >[2]/dev/null &
|
||||||
|
}
|
55
werc/bin/template.awk
Executable file
55
werc/bin/template.awk
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/awk -f
|
||||||
|
function pr(str) {
|
||||||
|
if(lastc !~ "[{(]")
|
||||||
|
gsub(/'/, "''", str)
|
||||||
|
printf "%s", str
|
||||||
|
}
|
||||||
|
function trans(c) {
|
||||||
|
printf "%s", end
|
||||||
|
|
||||||
|
lastc = c
|
||||||
|
end = "\n"
|
||||||
|
if(c == "%")
|
||||||
|
end = ""
|
||||||
|
else if(c == "(")
|
||||||
|
printf "echo -n "
|
||||||
|
else if(c ~ "[})]") {
|
||||||
|
end = "'\n"
|
||||||
|
printf "echo -n '"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
lastc = "{"
|
||||||
|
trans("}")
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
print end
|
||||||
|
}
|
||||||
|
|
||||||
|
/^%/ && $0 !~ /^%[{()}%]/ && lastc !~ /[({]/ {
|
||||||
|
trans("%")
|
||||||
|
print substr($0, 2)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if(lastc == "%")
|
||||||
|
trans("}")
|
||||||
|
n = split($0, a, "%")
|
||||||
|
pr(a[1])
|
||||||
|
for(i=2; i<=n; i++) {
|
||||||
|
c = substr(a[i], 1, 1)
|
||||||
|
rest = substr(a[i], 2)
|
||||||
|
|
||||||
|
if((lastc !~ "[({]" && c ~ "[({]") ||
|
||||||
|
(lastc == "{" && c == "}") ||
|
||||||
|
(lastc == "(" && c == ")"))
|
||||||
|
trans(c)
|
||||||
|
else if(c == "%")
|
||||||
|
pr("%")
|
||||||
|
else
|
||||||
|
pr("%" c)
|
||||||
|
pr(rest)
|
||||||
|
}
|
||||||
|
pr("\n")
|
||||||
|
}
|
138
werc/bin/werc.rc
Executable file
138
werc/bin/werc.rc
Executable file
|
@ -0,0 +1,138 @@
|
||||||
|
#!/bin/rc
|
||||||
|
. ./cgilib.rc
|
||||||
|
. ./werclib.rc
|
||||||
|
. ./wercconf.rc
|
||||||
|
. ./corehandlers.rc
|
||||||
|
. ./fltr_cache.rc
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
forbidden_uri_chars='[^a-zA-Z0-9_+\-\/\.,:]'
|
||||||
|
difs=$ifs # Used to restore default ifs when needed
|
||||||
|
|
||||||
|
# Expected input: ls -F style, $sitedir/path/to/files/
|
||||||
|
# <ls -F+x><symlink hack><Useless?><hiden files >
|
||||||
|
dirfilter='s/\*$//; s,/+\./+,/,g; s,^\./,,; /\/[._][^\/]/d; /'$forbidden_uri_chars'/d; /\/sitemap\.xml$/d; /\/index\.(md|html|txt|tpl)$/d; /\/(robots|sitemap)\.txt$/d; /_werc\/?$/d; '
|
||||||
|
dirclean=' s/\.(md|html|txt)$//; '
|
||||||
|
|
||||||
|
# Careful, the proper p9p path might not be set until initrc.local is sourced
|
||||||
|
path=(. /bin ./bin)
|
||||||
|
|
||||||
|
res_tail='</body></html>'
|
||||||
|
http_content_type='text/html'
|
||||||
|
ll_add handlers_bar_left nav_tree
|
||||||
|
werc_apps=( apps/* )
|
||||||
|
werc_root=`{pwd}
|
||||||
|
sitesdir=sites
|
||||||
|
|
||||||
|
. ./etc/initrc
|
||||||
|
|
||||||
|
if(test -f etc/initrc.local)
|
||||||
|
. ./etc/initrc.local
|
||||||
|
|
||||||
|
for(a in $werc_apps)
|
||||||
|
. ./$a/app.rc
|
||||||
|
|
||||||
|
fn werc_exec_request {
|
||||||
|
site=$SERVER_NAME
|
||||||
|
base_url=http://$site:$SERVER_PORT
|
||||||
|
sitedir=$sitesdir/$site
|
||||||
|
headers=`{get_lib_file headers.tpl}
|
||||||
|
master_template=`{get_lib_file default_master.tpl}
|
||||||
|
current_date_time=`{date}
|
||||||
|
|
||||||
|
# Note: $REQUEST_URI is not officially in CGI 1.1, but seems to be de-facto
|
||||||
|
# Note: We only urldecode %5F->'_' because some sites (stackoverflow.com?) urlencode it in their links,
|
||||||
|
# perhaps we should completel urldecode the whole url.
|
||||||
|
req_path=`{echo -n $REQUEST_URI | sed 's/\?.*//; s!//+!/!g; s/%5[Ff]/_/g; s/'^$forbidden_uri_chars^'//g; s/\.\.*/./g; 1q'}
|
||||||
|
req_url=$base_url^$req_path
|
||||||
|
local_path=$sitedir$req_path
|
||||||
|
local_file=''
|
||||||
|
ifs='/' { args=`{echo -n $req_path} }
|
||||||
|
|
||||||
|
# Preload post args for templates where cgi's stdin is not accessible
|
||||||
|
if(~ $REQUEST_METHOD POST) {
|
||||||
|
load_post_args
|
||||||
|
login_user
|
||||||
|
}
|
||||||
|
|
||||||
|
if(~ $req_path */index)
|
||||||
|
perm_redirect `{echo $req_path | sed 's,/index$,/,'}
|
||||||
|
|
||||||
|
if(~ $local_path */) {
|
||||||
|
if(test -d $local_path)
|
||||||
|
local_path=$local_path^'index'
|
||||||
|
# XXX: This redir might step on apps with synthetic dirs.
|
||||||
|
if not if(ls `{basename -d $local_path}^* >/dev/null >[2]/dev/null)
|
||||||
|
perm_redirect `{echo $req_path|sed 's,/+$,,'}
|
||||||
|
}
|
||||||
|
if not if(~ $req_path *'.' *',' *';' *':')
|
||||||
|
perm_redirect `{echo $req_path | sed 's/[.,;:)]$//'}
|
||||||
|
if not if(test -d $local_path)
|
||||||
|
perm_redirect $req_path^'/'
|
||||||
|
|
||||||
|
if(! ~ $#args 0)
|
||||||
|
ifs=$NEW_LINE { pageTitle=`{ echo $args|sed -e 's/ / - /g' -e 's/([a-z])-([a-z])/\1 \2/g' -e 's/_/ /g' } }
|
||||||
|
|
||||||
|
cd $sitedir
|
||||||
|
req_paths_list='/' # Note: req_paths_list doesn't include 'stnythetic' dirs.
|
||||||
|
conf_wd='/' # Used in config files to know where we are in the document tree.
|
||||||
|
if(test -f _werc/config)
|
||||||
|
. _werc/config
|
||||||
|
for(i in $args) {
|
||||||
|
conf_wd=$conf_wd^$i
|
||||||
|
req_paths_list=($req_paths_list $conf_wd)
|
||||||
|
if(test -d $i) {
|
||||||
|
conf_wd=$conf_wd'/'
|
||||||
|
cd $i
|
||||||
|
if(test -f _werc/config)
|
||||||
|
. _werc/config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cd $werc_root
|
||||||
|
|
||||||
|
if(~ $#perm_redir_to 1)
|
||||||
|
perm_redirect $perm_redir_to
|
||||||
|
for(l in $perm_redir_patterns) {
|
||||||
|
p=$$l
|
||||||
|
r=$p(1)
|
||||||
|
# If target is absolute, then patern must match whole string
|
||||||
|
if(~ $p(2) http://* https://*)
|
||||||
|
r='^'$r
|
||||||
|
t=`{ echo $req_path | sed 's!'^$r^'!'^$p(2)^'!' } # Malicious danger!
|
||||||
|
|
||||||
|
if(! ~ $"t '' $req_path)
|
||||||
|
perm_redirect $t
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_handlers
|
||||||
|
|
||||||
|
|
||||||
|
# Set Page title
|
||||||
|
if(! ~ $local_file '') {
|
||||||
|
t=`{get_file_title $local_file}
|
||||||
|
if(! ~ $"t '')
|
||||||
|
pageTitle=$t
|
||||||
|
}
|
||||||
|
|
||||||
|
# XXX Is this never true? because we set pageTitle earlier based on url.
|
||||||
|
if(~ $"pageTitle '')
|
||||||
|
pageTitle=$"siteTitle' '$"siteSubTitle
|
||||||
|
# if not
|
||||||
|
# pageTitle=$"pageTitle' | '$"siteTitle' '$"siteSubTitle
|
||||||
|
|
||||||
|
for(h in $extraHttpHeaders)
|
||||||
|
echo $h
|
||||||
|
echo Content-Type: $http_content_type
|
||||||
|
echo # End of HTTP headers
|
||||||
|
|
||||||
|
if(! ~ $#debug 0)
|
||||||
|
dprint $"SERVER_NAME^$"REQUEST_URI - $"HTTP_USER_AGENT - $"REQUEST_METHOD - $"handler_body_main - $"master_template
|
||||||
|
|
||||||
|
if(~ $REQUEST_METHOD HEAD)
|
||||||
|
exit
|
||||||
|
|
||||||
|
template $headers $master_template # | awk_buffer
|
||||||
|
echo $res_tail
|
||||||
|
}
|
||||||
|
|
||||||
|
werc_exec_request
|
5
werc/bin/werc_errlog_wrap.rc
Executable file
5
werc/bin/werc_errlog_wrap.rc
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/rc
|
||||||
|
|
||||||
|
# This is a wrapper script for broken http servers like recent lighttpd versions which throw away cgi's stderr.
|
||||||
|
|
||||||
|
./werc.rc >>[2]/tmp/wlog.txt
|
19
werc/bin/wercconf.rc
Executable file
19
werc/bin/wercconf.rc
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
# To be used from config files
|
||||||
|
fn conf_perm_redirect {
|
||||||
|
if(~ $#* 1)
|
||||||
|
perm_redir_to=$1
|
||||||
|
if not
|
||||||
|
ll_addh perm_redir_patterns $1 $2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conf_hide_paths {
|
||||||
|
for(i in $*)
|
||||||
|
dirfilter=$dirfilter^'/'^`{echo $sitedir$conf_wd$i|sed 's!/+!\\/!g'}^'/d; '
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usually will be called from within conf_enable_foo
|
||||||
|
fn conf_enable_app {
|
||||||
|
# Note: maybe we should add test -d apps/$1/?
|
||||||
|
if(! ~ $1 $enabled_apps)
|
||||||
|
enabled_apps=( $enabled_apps $1 )
|
||||||
|
}
|
393
werc/bin/werclib.rc
Executable file
393
werc/bin/werclib.rc
Executable file
|
@ -0,0 +1,393 @@
|
||||||
|
fn get_lib_file {
|
||||||
|
if(! ~ $#sitedir 0 && test -f $sitedir/_werc/lib/$1)
|
||||||
|
echo -n $sitedir/_werc/lib/$1
|
||||||
|
if not if(! ~ $#masterSite 0 && test -f $sitesdir/$masterSite/_werc/lib/$1)
|
||||||
|
echo -n $sitesdir/$masterSite/_werc/lib/$1
|
||||||
|
if not if(test -f lib/$1)
|
||||||
|
echo -n lib/$1
|
||||||
|
if not if(~ $#* 2)
|
||||||
|
echo -n $2
|
||||||
|
if not
|
||||||
|
status='Can''t find lib file: '$1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn template { awk -f bin/template.awk $* | rc $rcargs }
|
||||||
|
|
||||||
|
# Auth code
|
||||||
|
# TODO: check http://cookies.lcs.mit.edu/pubs/webauth:tr.pdf
|
||||||
|
allowed_user_chars='[a-zA-Z0-9_]'
|
||||||
|
# Cookie format: WERC_USER: name:timestamp:hash(name.timestamp.password)
|
||||||
|
# login_user can't be used from a template because it sets a cookie
|
||||||
|
fn login_user {
|
||||||
|
# Note: we set the cookie even if it is already there.
|
||||||
|
if(get_user $*)
|
||||||
|
set_cookie werc_user $"logged_user^':0:'^$"logged_password
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check login status, if called with group arg we check membership too
|
||||||
|
fn check_user {
|
||||||
|
get_user
|
||||||
|
g=($* admin)
|
||||||
|
_status=$status
|
||||||
|
if(! ~ $"_status '')
|
||||||
|
_status=(Not logged in: $"_status)
|
||||||
|
if not if(! ~ $#* 0 && ! ~ $logged_user $* && ! grep -s '^'^$logged_user^'$' $werc_root/etc/users/$g/members >[2]/dev/null)
|
||||||
|
_status=(User $logged_user not in: $*)
|
||||||
|
status=$_status
|
||||||
|
}
|
||||||
|
|
||||||
|
# If not logged in, try to get user login info from POST or from cookie
|
||||||
|
fn get_user {
|
||||||
|
if(~ $#logged_user 0) {
|
||||||
|
if(~ $#* 2) {
|
||||||
|
user_name=$1
|
||||||
|
user_password=$2
|
||||||
|
}
|
||||||
|
if not if(~ $REQUEST_METHOD POST)
|
||||||
|
get_post_args user_name user_password
|
||||||
|
|
||||||
|
if(~ $#user_name 0) {
|
||||||
|
ifs=':' { cu=`{ifs=$difs {get_cookie werc_user} | tr -d $NEW_LINE} }
|
||||||
|
if(! ~ $#cu 0) {
|
||||||
|
user_name=$cu(1)
|
||||||
|
user_password=$cu(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auth_user $user_name $user_password
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
status=()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if user_name and user_password represent a valid user account
|
||||||
|
# If valid, 'log in' by setting logged_user
|
||||||
|
fn auth_user {
|
||||||
|
user_name=$1
|
||||||
|
user_password=$2
|
||||||
|
|
||||||
|
pfile=$werc_root/etc/users/$"user_name/password
|
||||||
|
if(~ $#user_name 0 || ~ $#user_password 0)
|
||||||
|
status=('Auth: missing user name or pass: '^$"user_name^' / '^$"user_password)
|
||||||
|
if not if(! test -f $pfile)
|
||||||
|
status=('Auth: cant find '^$pfile)
|
||||||
|
if not if(! test -s $pfile || ! ~ $user_password `{cat $pfile})
|
||||||
|
status=('Auth: Pass '$user_password' doesnt match '^`{cat $pfile})
|
||||||
|
if not {
|
||||||
|
logged_user=$user_name
|
||||||
|
logged_password=$user_password
|
||||||
|
dprint Auth: success
|
||||||
|
status=()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn user_controls {
|
||||||
|
echo User: $"logged_user
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# .md '(meta-)data' extract
|
||||||
|
fn get_md_file_attr {
|
||||||
|
sed -n '/^\* '$2': /p; /^\* '$2': /q; /^$/q' < $1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# File title extraction
|
||||||
|
fn get_md_title {
|
||||||
|
#sed 's/^(................................................................[^ ]*).*$/\1/g; 1q' < $1
|
||||||
|
sed -n -e '1N; /^.*\n===*$/N; /.*\n===*\n *$/!b' -e 's/\n==*\n//p' < $1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_html_title {
|
||||||
|
t=`{sed -n '32q; s/^.*<[Tt][Ii][Tt][Ll][Ee]> *([^<]+) *(<\/[Tt][Ii][Tt][Ll][Ee]>.*)?$/\1/p' < $1}
|
||||||
|
|
||||||
|
# As a backup we might want to pick the first 'non-tag' text in the file with:
|
||||||
|
if(~ $"t '')
|
||||||
|
t=`{sed -n -e 's/^(<[^>]+>)*([^<]+).*/\2/p; 32q' < $1 | sed 1q}
|
||||||
|
|
||||||
|
echo $t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_file_title {
|
||||||
|
if (~ $1 *.md)
|
||||||
|
get_md_title $1
|
||||||
|
if not if(~ $1 *.html)
|
||||||
|
get_html_title $1
|
||||||
|
if not if(~ $1 */) {
|
||||||
|
if(test -f $1/index.md)
|
||||||
|
get_md_title $1/index.md
|
||||||
|
if not if(test -f $1/index.html)
|
||||||
|
get_html_title $1/index.html
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ndate {
|
||||||
|
if(~ $#* 7)
|
||||||
|
date=$*(2-)
|
||||||
|
if not
|
||||||
|
date=`{date}
|
||||||
|
switch($date(2)){
|
||||||
|
case Jan; mo=01
|
||||||
|
case Feb; mo=02
|
||||||
|
case Mar; mo=03
|
||||||
|
case Apr; mo=04
|
||||||
|
case May; mo=05
|
||||||
|
case Jun; mo=06
|
||||||
|
case Jul; mo=07
|
||||||
|
case Aug; mo=08
|
||||||
|
case Sep; mo=09
|
||||||
|
case Oct; mo=10
|
||||||
|
case Nov; mo=11
|
||||||
|
case Dec; mo=12
|
||||||
|
}
|
||||||
|
switch($date(3)){
|
||||||
|
case [0-9]
|
||||||
|
da=0^$date(3)
|
||||||
|
case *
|
||||||
|
da=$date(3)
|
||||||
|
}
|
||||||
|
switch($date(5)){
|
||||||
|
case A; tz=+0100
|
||||||
|
case ADT; tz=-0300
|
||||||
|
case AFT; tz=+430
|
||||||
|
case AKDT; tz=-0800
|
||||||
|
case AKST; tz=-0900
|
||||||
|
case ALMT; tz=+0600
|
||||||
|
case AMST; tz=-0300
|
||||||
|
case AMT; tz=-0400
|
||||||
|
case ANAST; tz=+1200
|
||||||
|
case ANAT; tz=+1200
|
||||||
|
case AQTT; tz=+0500
|
||||||
|
case ART; tz=-0300
|
||||||
|
case AST; tz=-0400
|
||||||
|
case AZOST; tz=+0000
|
||||||
|
case AZOT; tz=-0100
|
||||||
|
case AZST; tz=+0500
|
||||||
|
case AZT; tz=+0400
|
||||||
|
case B; tz=+0200
|
||||||
|
case BNT; tz=+0800
|
||||||
|
case BOT; tz=-0400
|
||||||
|
case BRST; tz=-0200
|
||||||
|
case BRT; tz=-0300
|
||||||
|
case BST; tz=+0100
|
||||||
|
case BTT; tz=+0600
|
||||||
|
case C; tz=+0300
|
||||||
|
case CAST; tz=+0800
|
||||||
|
case CAT; tz=+0200
|
||||||
|
case CCT; tz=+0630
|
||||||
|
case CDT; tz=-0500
|
||||||
|
case CEST; tz=+0200
|
||||||
|
case CET; tz=+0100
|
||||||
|
case CHADT; tz=+1345
|
||||||
|
case CHAST; tz=+1245
|
||||||
|
case CKT; tz=-1000
|
||||||
|
case CLST; tz=-0300
|
||||||
|
case CLT; tz=-0400
|
||||||
|
case COT; tz=-0500
|
||||||
|
case CST; tz=-0600
|
||||||
|
case CVT; tz=-0100
|
||||||
|
case CXT; tz=+0700
|
||||||
|
case ChST; tz=+1000
|
||||||
|
case D; tz=+0400
|
||||||
|
case DAVT; tz=+0700
|
||||||
|
case E; tz=+0500
|
||||||
|
case EASST; tz=-0500
|
||||||
|
case EAST; tz=-0600
|
||||||
|
case EAT; tz=+0300
|
||||||
|
case ECT; tz=-0500
|
||||||
|
case EDT; tz=-0400
|
||||||
|
case EEST; tz=+0300
|
||||||
|
case EET; tz=+0200
|
||||||
|
case EGST; tz=+0000
|
||||||
|
case EGT; tz=-0100
|
||||||
|
case EST; tz=-0500
|
||||||
|
case ET; tz=-0500
|
||||||
|
case F; tz=+0600
|
||||||
|
case FJST; tz=+1300
|
||||||
|
case FJT; tz=+1200
|
||||||
|
case FKST; tz=-0300
|
||||||
|
case FKT; tz=-0400
|
||||||
|
case FNT; tz=-0200
|
||||||
|
case G; tz=+0700
|
||||||
|
case GALT; tz=-0600
|
||||||
|
case GAMT; tz=-0900
|
||||||
|
case GET; tz=+0400
|
||||||
|
case GFT; tz=-0300
|
||||||
|
case GILT; tz=+1200
|
||||||
|
case GMT; tz=+0000
|
||||||
|
case GST; tz=+0400
|
||||||
|
case GYT; tz=-0400
|
||||||
|
case H; tz=+0800
|
||||||
|
case HAA; tz=-0300
|
||||||
|
case HAC; tz=-0500
|
||||||
|
case HADT; tz=-0900
|
||||||
|
case HAE; tz=-0400
|
||||||
|
case HAP; tz=-0700
|
||||||
|
case HAR; tz=-0600
|
||||||
|
case HAST; tz=-1000
|
||||||
|
case HAT; tz=-0230
|
||||||
|
case HAY; tz=-0800
|
||||||
|
case HKT; tz=+0800
|
||||||
|
case HLV; tz=-0430
|
||||||
|
case HNA; tz=-0400
|
||||||
|
case HNC; tz=-0600
|
||||||
|
case HNE; tz=-0500
|
||||||
|
case HNP; tz=-0800
|
||||||
|
case HNR; tz=-0700
|
||||||
|
case HNT; tz=-0330
|
||||||
|
case HNY; tz=-0900
|
||||||
|
case HOVT; tz=+0700
|
||||||
|
case I; tz=+0900
|
||||||
|
case ICT; tz=+0700
|
||||||
|
case IDT; tz=+0300
|
||||||
|
case IOT; tz=+0600
|
||||||
|
case IRDT; tz=+0430
|
||||||
|
case IRKST; tz=+0900
|
||||||
|
case IRKT; tz=+0800
|
||||||
|
case IRST; tz=+0330
|
||||||
|
case IST; tz=+0200
|
||||||
|
case JST; tz=+0900
|
||||||
|
case K; tz=+1000
|
||||||
|
case KGT; tz=+0600
|
||||||
|
case KRAST; tz=+0800
|
||||||
|
case KRAT; tz=+0700
|
||||||
|
case KST; tz=+0900
|
||||||
|
case KUYT; tz=+0400
|
||||||
|
case L; tz=+1100
|
||||||
|
case LHDT; tz=+1100
|
||||||
|
case LHST; tz=+1030
|
||||||
|
case LINT; tz=+1400
|
||||||
|
case M; tz=+1200
|
||||||
|
case MAGST; tz=+1200
|
||||||
|
case MAGT; tz=+1100
|
||||||
|
case MART; tz=-0930
|
||||||
|
case MAWT; tz=+0500
|
||||||
|
case MDT; tz=-0600
|
||||||
|
case MHT; tz=+1200
|
||||||
|
case MMT; tz=+0630
|
||||||
|
case MSD; tz=+0400
|
||||||
|
case MSK; tz=+0300
|
||||||
|
case MST; tz=-0700
|
||||||
|
case MUT; tz=+0400
|
||||||
|
case MVT; tz=+0500
|
||||||
|
case MYT; tz=+0800
|
||||||
|
case N; tz=-0100
|
||||||
|
case NCT; tz=+1100
|
||||||
|
case NDT; tz=-0230
|
||||||
|
case NFT; tz=+1130
|
||||||
|
case NOVST; tz=+0700
|
||||||
|
case NOVT; tz=+0600
|
||||||
|
case NPT; tz=+0545
|
||||||
|
case NST; tz=-0330
|
||||||
|
case NUT; tz=-1100
|
||||||
|
case NZDT; tz=+1300
|
||||||
|
case NZST; tz=+1200
|
||||||
|
case O; tz=-0200
|
||||||
|
case OMSST; tz=+0700
|
||||||
|
case OMST; tz=+0600
|
||||||
|
case P; tz=-0300
|
||||||
|
case PDT; tz=-0700
|
||||||
|
case PET; tz=-0500
|
||||||
|
case PETST; tz=+1200
|
||||||
|
case PETT; tz=+1200
|
||||||
|
case PGT; tz=+1000
|
||||||
|
case PHOT; tz=+1300
|
||||||
|
case PHT; tz=+0800
|
||||||
|
case PKT; tz=+0500
|
||||||
|
case PMDT; tz=-0200
|
||||||
|
case PMST; tz=-0300
|
||||||
|
case PONT; tz=+1100
|
||||||
|
case PST; tz=-0800
|
||||||
|
case PT; tz=-0800
|
||||||
|
case PWT; tz=+0900
|
||||||
|
case PYST; tz=-0300
|
||||||
|
case PYT; tz=-0400
|
||||||
|
case Q; tz=-0400
|
||||||
|
case R; tz=-0500
|
||||||
|
case RET; tz=+0400
|
||||||
|
case S; tz=-0600
|
||||||
|
case SAMT; tz=+0400
|
||||||
|
case SAST; tz=+0200
|
||||||
|
case SBT; tz=+1100
|
||||||
|
case SCT; tz=+0400
|
||||||
|
case SGT; tz=+0800
|
||||||
|
case SRT; tz=-0300
|
||||||
|
case SST; tz=-1100
|
||||||
|
case T; tz=-0700
|
||||||
|
case TAHT; tz=-1000
|
||||||
|
case TFT; tz=+0500
|
||||||
|
case TJT; tz=+0500
|
||||||
|
case TKT; tz=-1000
|
||||||
|
case TLT; tz=+0900
|
||||||
|
case TMT; tz=+0500
|
||||||
|
case TVT; tz=+1200
|
||||||
|
case U; tz=-0800
|
||||||
|
case ULAT; tz=+0800
|
||||||
|
case UYST; tz=-0200
|
||||||
|
case UYT; tz=-0300
|
||||||
|
case UZT; tz=+0500
|
||||||
|
case V; tz=-0900
|
||||||
|
case VET; tz=-0430
|
||||||
|
case VLAST; tz=+1100
|
||||||
|
case VLAT; tz=+1000
|
||||||
|
case VUT; tz=+1100
|
||||||
|
case W; tz=-1000
|
||||||
|
case WAST; tz=+0200
|
||||||
|
case WAT; tz=+0100
|
||||||
|
case WDT; tz=+0900
|
||||||
|
case WEST; tz=+0100
|
||||||
|
case WET; tz=+0000
|
||||||
|
case WFT; tz=+1200
|
||||||
|
case WGST; tz=-0200
|
||||||
|
case WGT; tz=-0300
|
||||||
|
case WIB; tz=+0700
|
||||||
|
case WIT; tz=+0900
|
||||||
|
case WITA; tz=+0800
|
||||||
|
case WST; tz=+0800
|
||||||
|
case WT; tz=+0000
|
||||||
|
case X; tz=-1100
|
||||||
|
case Y; tz=-1200
|
||||||
|
case YAKST; tz=+1000
|
||||||
|
case YAKT; tz=+0900
|
||||||
|
case YAPT; tz=+1000
|
||||||
|
case YEKST; tz=+0600
|
||||||
|
case YEKT; tz=+0500
|
||||||
|
case Z; tz=+0000
|
||||||
|
}
|
||||||
|
switch($1){
|
||||||
|
case -a # rfc3339
|
||||||
|
tz=`{echo $tz | sed 's/00$/:00/'}
|
||||||
|
echo $date(6)^-$mo-$da^T^$date(4)^$tz
|
||||||
|
case -i # iso-8601 lite
|
||||||
|
echo $date(6)^-$mo-$da
|
||||||
|
case -m # rfc2822
|
||||||
|
echo $date(1)^, $da $date(2) $date(6) $date(4) $tz
|
||||||
|
case -t # iso-8601
|
||||||
|
echo $date(6)^-$mo-$da^T^$date(4)^$tz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
##########################################################################
|
||||||
|
#app_blog_methods = ( _post index.rss )
|
||||||
|
#fn app_blog__post {
|
||||||
|
# echo
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
#app_blog___default {
|
||||||
|
# if (~ $blog)
|
||||||
|
# call_app blogpost
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
## --
|
||||||
|
#app_blogpost_methods = ( comment _edit )
|
||||||
|
#
|
||||||
|
#fn app_blogpost_comment {
|
||||||
|
# call_app comments
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
## --
|
||||||
|
#app_comments_methods = ( _post _edit )
|
||||||
|
#
|
||||||
|
#fn app_comments___default {
|
||||||
|
#
|
||||||
|
#}
|
40
werc/etc/initrc
Normal file
40
werc/etc/initrc
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# This file contains the default werc settings.
|
||||||
|
#
|
||||||
|
# DO NOT EDIT, to customize copy to etc/initrc.local and edit at will.
|
||||||
|
#
|
||||||
|
# Some settings can also be set for a specific site or directory in their
|
||||||
|
# respective _werc/config or their $masterSite/_werc/config file.
|
||||||
|
|
||||||
|
# General options
|
||||||
|
|
||||||
|
# Location of your Plan 9 from User Space installation (usually /usr/local/plan9)
|
||||||
|
PLAN9=
|
||||||
|
plan9port=$PLAN9
|
||||||
|
|
||||||
|
# If you use 9base, it should point to your 9base root, try for example:
|
||||||
|
#plan9port=/usr/lib/9base # This is the default 9base install path in Debian.
|
||||||
|
|
||||||
|
# If rc has not been copied to /bin/rc you will also need to change
|
||||||
|
# the #! line in bin/*.rc!
|
||||||
|
|
||||||
|
# Path, make sure the plan9port /bin directory is included before /bin
|
||||||
|
# Keep '.' in path! It is needed.
|
||||||
|
path=($plan9port/bin . ./bin ./bin/contrib /bin /usr/bin)
|
||||||
|
|
||||||
|
# Set this to your favorite markdown formatter, eg., markdown.pl (fltr_cache
|
||||||
|
# takes as an argument a filter, in the default configuration markdown.pl, that
|
||||||
|
# caches output) Note that some werc components assume a markdown-like
|
||||||
|
# formatter, but all major functionality should should be formatter agnostic.
|
||||||
|
#formatter=(fltr_cache markdown.pl)
|
||||||
|
formatter=(fltr_cache md2html.awk) # no perl for old men
|
||||||
|
|
||||||
|
# Enable debugging, to disable set to ()
|
||||||
|
debug=true
|
||||||
|
|
||||||
|
# Globally enabled apps
|
||||||
|
enabled_apps=()
|
||||||
|
|
||||||
|
# Default site variables, must be set in initrc.local or _werc/config, only siteTitle is required.
|
||||||
|
#masterSite=cat-v.org # Not required!
|
||||||
|
#siteTitle='cat-v'
|
||||||
|
#siteSubTitle='Considered harmful'
|
1
werc/etc/users/GROUP_AND_USER_ACCOUNTS
Normal file
1
werc/etc/users/GROUP_AND_USER_ACCOUNTS
Normal file
|
@ -0,0 +1 @@
|
||||||
|
This is just a dummy file to force hg to preserve this directory that is used to store user and group account information.
|
4
werc/lib/404.tpl
Normal file
4
werc/lib/404.tpl
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<h1>The requested document at '<i>%($"req_path%)</i>' doesn't exist</h1>
|
||||||
|
<img src="/pub/404coffee.png" alt="404 error: coffee not found">
|
||||||
|
<h4>maybe it is in the <a href="/sitemap">sitemap</a>?</h4>
|
||||||
|
<hr>
|
26
werc/lib/default_master.tpl
Normal file
26
werc/lib/default_master.tpl
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<header>
|
||||||
|
<nav>
|
||||||
|
% cat `{ get_lib_file top_bar.inc }
|
||||||
|
</nav>
|
||||||
|
<h1><a href="/">%($"siteTitle%) <span id="headerSubTitle">%($"siteSubTitle%)</span></a></h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
% if(! ~ $#handlers_bar_left 0) {
|
||||||
|
<nav id="side-bar">
|
||||||
|
% for(h in $handlers_bar_left) {
|
||||||
|
<div>
|
||||||
|
% run_handler $$h
|
||||||
|
</div>
|
||||||
|
% }
|
||||||
|
</nav>
|
||||||
|
% }
|
||||||
|
|
||||||
|
<article>
|
||||||
|
% run_handlers $handlers_body_head
|
||||||
|
% run_handler $handler_body_main
|
||||||
|
% run_handlers $handlers_body_foot
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
% cat `{ get_lib_file footer.inc }
|
||||||
|
</footer>
|
2
werc/lib/footer.inc
Normal file
2
werc/lib/footer.inc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<div><a href="http://werc.cat-v.org/">Powered by werc</a></div>
|
||||||
|
|
31
werc/lib/headers.tpl
Normal file
31
werc/lib/headers.tpl
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<title>%($pageTitle%)</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/pub/style/style.css" type="text/css" media="screen, handheld" title="default">
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" type="image/vnd.microsoft.icon">
|
||||||
|
% if(test -f $sitedir/_werc/pub/style.css)
|
||||||
|
% echo ' <link rel="stylesheet" href="/_werc/pub/style.css" type="text/css" media="screen" title="default">'
|
||||||
|
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
% # Legacy charset declaration for backards compatibility with non-html5 browsers.
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
% if(! ~ $#meta_description 0)
|
||||||
|
% echo ' <meta name="description" content="'$"meta_description'">'
|
||||||
|
% if(! ~ $#meta_keywords 0)
|
||||||
|
% echo ' <meta name="keywords" content="'$"meta_keywords'">'
|
||||||
|
|
||||||
|
% h = `{get_lib_file headers.inc}
|
||||||
|
% if(! ~ $#h 0)
|
||||||
|
% cat $h
|
||||||
|
|
||||||
|
%($"extraHeaders%)
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
8
werc/lib/top_bar.inc
Normal file
8
werc/lib/top_bar.inc
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="left>
|
||||||
|
<a href="https://owen.bellz.org">escape</a> |
|
||||||
|
<a href="//withdrawal.owen.bellz.org">withdrawal</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<a href="/sitemap">site map</a>
|
||||||
|
</div>
|
BIN
werc/pub/404coffee.png
Normal file
BIN
werc/pub/404coffee.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 774 KiB |
BIN
werc/pub/default_favicon.ico
Executable file
BIN
werc/pub/default_favicon.ico
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
werc/pub/style/imgs/sgl.png
Executable file
BIN
werc/pub/style/imgs/sgl.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
292
werc/pub/style/sinorca-screen-alt.css
Executable file
292
werc/pub/style/sinorca-screen-alt.css
Executable file
|
@ -0,0 +1,292 @@
|
||||||
|
/***********************************************
|
||||||
|
* TITLE: Sinorca Alterative Screen Stylesheet *
|
||||||
|
* URI : sinorca/sinorca-screen-alt.css *
|
||||||
|
* MODIF: 2003-May-13 18:48 +0800 *
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Common Styles ##### */
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
font-family: verdana, helvetica, arial, sans-serif;
|
||||||
|
font-size: 71%; /* Enables font size scaling in MSIE */
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html > body {
|
||||||
|
font-size: 8.5pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
acronym, .titleTip {
|
||||||
|
border-bottom: 1px dotted rgb(153,153,153);
|
||||||
|
cursor: help;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0.4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doNotDisplay {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallCaps {
|
||||||
|
font-size: 110%;
|
||||||
|
font-variant: small-caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Header ##### */
|
||||||
|
|
||||||
|
.superHeader {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 91%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.5ex 0 0.25ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .left {
|
||||||
|
position: absolute;
|
||||||
|
left: 1.5mm;
|
||||||
|
top: 0.75ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .right {
|
||||||
|
position: absolute;
|
||||||
|
right: 1.5mm;
|
||||||
|
top: 0.75ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.midHeader {
|
||||||
|
color: rgb(39,78,144);
|
||||||
|
background-color: rgb(140,170,230);
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerTitle {
|
||||||
|
font-size: 337%;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0 0 0 4mm;
|
||||||
|
padding: 0.25ex 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(0,51,153);
|
||||||
|
margin: 0;
|
||||||
|
padding: 1ex 1ex 1ex 1.5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.75ex 0 0.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .highlight, .subHeader .highlight {
|
||||||
|
color: rgb(253,160,91);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Side Boxes ##### */
|
||||||
|
|
||||||
|
#side-bar {
|
||||||
|
width: 14em;
|
||||||
|
margin: 2.5em 0 0 1.25mm;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
body > #side-bar {
|
||||||
|
margin-left: 2.5mm; /* Circumvents a rendering bug in MSIE (6.0) */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarTitle {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.4ex 0 0.4ex 0.6ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar ul {
|
||||||
|
list-style-type: none;
|
||||||
|
list-style-position: outside;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 2.25em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE (6.0) */
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar a, .thisPage {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1.3ex 2ex;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thisPage {
|
||||||
|
color: black;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar a:hover {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarText {
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 0 0 2.5em 0;
|
||||||
|
padding: 1ex 0.5ex 0 0.5ex;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarText + .sideBarText { /* Not recognised by MSIE (6.0) */
|
||||||
|
margin-top: -1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar .sideBarText a {
|
||||||
|
text-decoration: underline;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar .sideBarText a:hover {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Main Copy ##### */
|
||||||
|
|
||||||
|
#main-copy {
|
||||||
|
color: black;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: justify;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: -1em 0 0 15em;
|
||||||
|
padding: 0.5mm 5mm 5mm 5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bodyText {
|
||||||
|
margin: 0 0 0 15.5em;
|
||||||
|
padding: 2mm 5mm 2mm 5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#main-copy p {
|
||||||
|
margin: 1em 1ex 2em 1ex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy a {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy h1 {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 145.5%;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 2em 0 0 0;
|
||||||
|
padding: 0.5ex 0 0.5ex 0.6ex;
|
||||||
|
border-bottom: 1px solid rgb(0,102,204);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy .topOfPage {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 91%;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 3ex 1ex 0 0;
|
||||||
|
padding: 0;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin: 1em 1ex 2em 1ex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin: 0 0 2em 2em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Footer ##### */
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
font-size: 91%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1em 2.5mm 2.5ex 2.5mm;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .left {
|
||||||
|
text-align: left;
|
||||||
|
line-height: 1.45em;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .right {
|
||||||
|
text-align: right;
|
||||||
|
line-height: 1.45em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
19
werc/pub/style/style.css
Normal file
19
werc/pub/style/style.css
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
body { display: flex; flex-wrap: wrap; font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; }
|
||||||
|
header { flex-basis: 100%; flex-shrink: 0; }
|
||||||
|
article { flex-basis: 60%; padding-left: 1em; }
|
||||||
|
footer { flex-basis: 100%; flex-shrink: 0; }
|
||||||
|
header nav { display: flex; justify-content: space-between; }
|
||||||
|
nav a, header a { text-decoration: none ; color: inherit; }
|
||||||
|
nav a:hover { text-decoration: underline; }
|
||||||
|
h1, h2, h3, h4, h5 { font-weight: normal; }
|
||||||
|
header h1 span { margin-left: 1em; font-size: 50%; font-style: italic; }
|
||||||
|
body > nav { flex-basis: content; padding-right: 1vw; min-width: 16em; }
|
||||||
|
nav ul { display: flex; flex-direction: column; list-style-type: none; list-style-position: outside; padding-left: 0; }
|
||||||
|
nav li ul { padding-left: 0.6em }
|
||||||
|
img { width: 100%; }
|
||||||
|
footer { display: flex; justify-content: space-between; }
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
330
werc/pub/style/style.werc140.css
Executable file
330
werc/pub/style/style.werc140.css
Executable file
|
@ -0,0 +1,330 @@
|
||||||
|
/* Default werc style */
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif;
|
||||||
|
font-size: 84%; /* Enables font size scaling in MSIE */
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* # Header # */
|
||||||
|
.superHeader {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader img { vertical-align: bottom; }
|
||||||
|
|
||||||
|
.superHeader a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 91%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.5ex 0 0.25ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
a { text-decoration: none; }
|
||||||
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
|
.superHeader div {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.40ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .left { left: 0.4em; }
|
||||||
|
.superHeader .right { right: 0.4em; }
|
||||||
|
|
||||||
|
.midHeader {
|
||||||
|
color: rgb(39,78,144);
|
||||||
|
background-color: rgb(140,170,230);
|
||||||
|
background-color: #ff6d06;
|
||||||
|
border: solid 0 black;
|
||||||
|
border-width: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerTitle {
|
||||||
|
color: black;
|
||||||
|
font-size: 233%;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0 0 0 4mm;
|
||||||
|
padding: 0.25ex 0;
|
||||||
|
}
|
||||||
|
#headerSubTitle {
|
||||||
|
font-size: 50%;
|
||||||
|
font-style: italic;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerTitle a { color: black; }
|
||||||
|
.headerTitle a:hover { text-decoration: none; }
|
||||||
|
|
||||||
|
.subHeader {
|
||||||
|
display: none;
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(0,51,153);
|
||||||
|
margin: 0;
|
||||||
|
padding: 1ex 1ex 1ex 1.5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.75ex 0 0.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .highlight, .subHeader .highlight {
|
||||||
|
color: rgb(253,160,91);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* # Side # */
|
||||||
|
#side-bar {
|
||||||
|
width: 16em;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar div {
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarTitle {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 0.5em 2mm;
|
||||||
|
padding: 1em 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar ul {
|
||||||
|
list-style-type: none;
|
||||||
|
list-style-position: outside;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0.3em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li ul {
|
||||||
|
padding-left: 0.6em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE 6.0 XXX should move to iehacks.css, this causes an ugly gap */
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar a {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.25em 1ex 0.25em 2mm;
|
||||||
|
display: block;
|
||||||
|
text-transform: capitalize;
|
||||||
|
font-weight: bold!important;
|
||||||
|
font-size: 102%;
|
||||||
|
border-left: white solid 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thisPage, .thisPage a {
|
||||||
|
color: black!important;
|
||||||
|
background-color: white;
|
||||||
|
padding-left: 5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar a:hover {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
border-left: black solid 0.2em;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarText {
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
padding: 0 1.5ex 0 2.5mm;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar .sideBarText a {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar .sideBarText a:hover {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* # Main Copy # */
|
||||||
|
#main-copy {
|
||||||
|
max-width: 70em;
|
||||||
|
color: black;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: justify;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 0em 0 0 16em;
|
||||||
|
padding: 0.5mm 5mm 5mm 5mm;
|
||||||
|
border-left: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bodyText {
|
||||||
|
margin: 0 0 0 15.5em;
|
||||||
|
padding: 2mm 5mm 2mm 5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy p {
|
||||||
|
margin: 1em 1ex 1em 1ex !important; /* Need !important so troff-generated pages don't look totally squezed */
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy a {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy a:hover {
|
||||||
|
color: rgb(100,135,220);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy h1, #main-copy h2 {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 145.5%;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 2em 0 0 0;
|
||||||
|
padding: 0.5ex 0 0.5ex 0.6ex;
|
||||||
|
border-bottom: 2px solid rgb(0,102,204);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy h2 {
|
||||||
|
font-size: 115.5%;
|
||||||
|
border-bottom: 1px solid rgb(0,102,204);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy .topOfPage {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 91%;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 3ex 1ex 0 0;
|
||||||
|
padding: 0;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin: 1em 1ex 2em 1ex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin: 0 0 2em 2em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* # Footer # */
|
||||||
|
#footer {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
padding: 1em;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .left {
|
||||||
|
text-align: left;
|
||||||
|
line-height: 1.55em;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .right {
|
||||||
|
text-align: right;
|
||||||
|
line-height: 1.45em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* GENERAL */
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: solid 1px black;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #abc;
|
||||||
|
border: solid 1px black;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
background-color: #def;
|
||||||
|
border: solid 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-width: 0px 0px 0.1em 0px;
|
||||||
|
border-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
acronym, .titleTip {
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
cursor: help;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0.4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-left: 2em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 1px solid blue;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallCaps {
|
||||||
|
font-size: 110%;
|
||||||
|
font-variant: small-caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doNotDisplay { display: none; }
|
||||||
|
|
||||||
|
|
||||||
|
.notify_errors,
|
||||||
|
.notify_notes,
|
||||||
|
.notify_success { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd; }
|
||||||
|
|
||||||
|
.notify_errors { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4; }
|
||||||
|
.notify_notes { background: #FFF6BF; color: #514721; border-color: #FFD324; }
|
||||||
|
.notify_success { background: #E6EFC2; color: #264409; border-color: #C6D880; }
|
||||||
|
.notify_errors a { color: #8a1f11; }
|
||||||
|
.notify_notes a { color: #514721; }
|
||||||
|
.notify_success a { color: #264409; }
|
||||||
|
|
||||||
|
|
||||||
|
/* # Page/Handler specific # */
|
||||||
|
h1.dir-list-head, ul.dir-list {
|
||||||
|
text-transform: capitalize;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
ul.sitemap-list a {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
330
werc/pub/style/style_old.css
Executable file
330
werc/pub/style/style_old.css
Executable file
|
@ -0,0 +1,330 @@
|
||||||
|
/* Old Default style */
|
||||||
|
/* ##### Common Styles ##### */
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
XXXbackground-color: rgb(240,240,240);
|
||||||
|
background-color: white;
|
||||||
|
font-family: verdana, helvetica, arial, sans-serif;
|
||||||
|
font-size: 71%; /* Enables font size scaling in MSIE */
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html > body {
|
||||||
|
font-size: 8.5pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
acronym, .titleTip {
|
||||||
|
border-bottom: 1px dotted rgb(153,153,153);
|
||||||
|
cursor: help;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0.4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doNotDisplay {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallCaps {
|
||||||
|
font-size: 110%;
|
||||||
|
font-variant: small-caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Header ##### */
|
||||||
|
|
||||||
|
.superHeader {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 91%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.5ex 0 0.25ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .left {
|
||||||
|
position: absolute;
|
||||||
|
left: 1.5mm;
|
||||||
|
top: 0.75ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .right {
|
||||||
|
position: absolute;
|
||||||
|
right: 1.5mm;
|
||||||
|
top: 0.75ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.midHeader {
|
||||||
|
color: rgb(39,78,144);
|
||||||
|
background-color: rgb(140,170,230);
|
||||||
|
border: solid 0 black;
|
||||||
|
border-width: 0.3em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerTitle {
|
||||||
|
color: black;
|
||||||
|
font-size: 337%;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0 0 0 4mm;
|
||||||
|
padding: 0.25ex 0;
|
||||||
|
}
|
||||||
|
#headerSubTitle {
|
||||||
|
font-size: 50%;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader {
|
||||||
|
display: none;
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(0,51,153);
|
||||||
|
margin: 0;
|
||||||
|
padding: 1ex 1ex 1ex 1.5mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.75ex 0 0.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subHeader a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.superHeader .highlight, .subHeader .highlight {
|
||||||
|
color: rgb(253,160,91);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Side Bar ##### */
|
||||||
|
|
||||||
|
#side-bar {
|
||||||
|
width: 15em;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
border-right: 1px solid rgb(153,153,153);
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar div {
|
||||||
|
border-bottom: 1px solid rgb(153,153,153);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarTitle {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 0.5em 2.5mm;
|
||||||
|
padding: 1em 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar ul {
|
||||||
|
list-style-type: none;
|
||||||
|
list-style-position: outside;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 1.1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE 6.0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar a, .thisPage {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
XXXtext-decoration: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.55em 1ex 0.55em 5mm;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thisPage {
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
padding-left: 5mm;
|
||||||
|
XXXborder-top: 1px solid rgb(153,153,153);
|
||||||
|
XXXborder-bottom: 1px solid rgb(153,153,153);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar a:hover {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sideBarText {
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
padding: 0 1.5ex 0 2.5mm;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar .sideBarText a {
|
||||||
|
text-decoration: underline;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#side-bar .sideBarText a:hover {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lighterBackground {
|
||||||
|
color: inherit;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Main Copy ##### */
|
||||||
|
|
||||||
|
#main-copy {
|
||||||
|
max-width: 90em;
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
text-align: justify;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 0 0 0 15em;
|
||||||
|
padding: 0.5mm 5mm 5mm 5mm;
|
||||||
|
border-left: 1px solid rgb(153,153,153);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy p {
|
||||||
|
margin: 1em 1ex 2em 1ex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy a {
|
||||||
|
color: rgb(0,102,204);
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy h1 {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
font-size: 100%;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 3em 0 0 0;
|
||||||
|
padding: 0.5ex 0 0.5ex 1ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy .topOfPage {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 91%;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 2.5ex 1ex 0 0; /* For MSIE */
|
||||||
|
padding: 0;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-copy > .topOfPage {
|
||||||
|
margin: 2.75ex 1ex 0 0; /* For fully standards-compliant user agents */
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin: 1em 1ex 2em 1ex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin: 0 0 2em 2em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### Footer ##### */
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(100,135,220);
|
||||||
|
font-size: 91%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1em 2.5mm 2.5ex 2.5mm;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .left {
|
||||||
|
line-height: 1.45em;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .right {
|
||||||
|
text-align: right;
|
||||||
|
line-height: 1.45em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a {
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* GENERAL */
|
||||||
|
/* Spam */
|
||||||
|
.spam {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
table {
|
||||||
|
border: solid 1px black;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #abc;
|
||||||
|
border: solid 1px black;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
background-color: #def;
|
||||||
|
border: solid 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-width: 0px 0px 0.1em 0px;
|
||||||
|
border-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spam table, .spam th, .spam td {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code */
|
||||||
|
pre {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
0
werc/sites/CREATE-SITE-DIRECTORIES-HERE
Normal file
0
werc/sites/CREATE-SITE-DIRECTORIES-HERE
Normal file
29
werc/tpl/_debug.tpl
Normal file
29
werc/tpl/_debug.tpl
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
% if(! ~ $#debug_shell 0) {
|
||||||
|
<form method="POST" name="prompt">
|
||||||
|
<input size="80" type="text" name="command" value="%($"post_arg_command%)">
|
||||||
|
<input type="submit" Value="Run">
|
||||||
|
</form>
|
||||||
|
<script language="javascript"><!--
|
||||||
|
document.prompt.command.focus()
|
||||||
|
//--></script>
|
||||||
|
|
||||||
|
%{
|
||||||
|
fn evl {
|
||||||
|
# Buffering is probably messing this up:
|
||||||
|
#rc -c 'flag x +;{'^$post_arg_command'} |[2] awk ''{print ">> "$0}'''
|
||||||
|
rc -c 'flag s +; flag x +;'^$post_arg_command
|
||||||
|
}
|
||||||
|
if(! ~ $#post_arg_command 0 && ! ~ $#post_arg_command '') {
|
||||||
|
echo '<hr><pre>'
|
||||||
|
evl | escape_html |[2] awk '{print "<b>"$0"</b>"}'
|
||||||
|
echo '</pre>'
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
% }
|
||||||
|
|
||||||
|
<hr><pre>
|
||||||
|
% env | escape_html
|
||||||
|
</pre><hr>
|
||||||
|
|
||||||
|
% umask
|
||||||
|
|
18
werc/tpl/_users/login.tpl
Normal file
18
werc/tpl/_users/login.tpl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<h1>User login</h1>
|
||||||
|
<br />
|
||||||
|
% if(check_user) {
|
||||||
|
You are logged in as: <b>%($logged_user%)</b>
|
||||||
|
% }
|
||||||
|
% if not {
|
||||||
|
% if (~ $REQUEST_METHOD POST)
|
||||||
|
% echo '<div class="notify_errors">Login failed!</div>'
|
||||||
|
<form method="POST" action="" style="text-align: right; float: left;">
|
||||||
|
<fieldset>
|
||||||
|
<label>User name: <input type="text" name="user_name" value="%($"post_arg_user_name%)"/></label><br>
|
||||||
|
<label>User password: <input type="password" name="user_password"></label><br>
|
||||||
|
<input name="s" type="submit" value="Login">
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
% }
|
||||||
|
|
||||||
|
<br style="clear:left">
|
67
werc/tpl/sitemap.tpl
Normal file
67
werc/tpl/sitemap.tpl
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<h1>Site map</h1>
|
||||||
|
|
||||||
|
%{
|
||||||
|
tmpfile=/tmp/werc_sitemap_$pid.txt
|
||||||
|
tmpfilex=/tmp/werc_sitemapx_$pid.txt
|
||||||
|
saveddf=$dirfilter
|
||||||
|
|
||||||
|
MON2NUM='s/Jan/01/; s/Feb/02/; s/Mar/03/; s/Apr/04/; s/May/05/; s/Jun/06/; s/Jul/07/; s/Aug/08/; s/Sep/09/; s/Oct/10/; s/Nov/11/; s/Dec/12/;'
|
||||||
|
|
||||||
|
fn get_mdate {
|
||||||
|
t=`{mtime $1}
|
||||||
|
t=`{date $t(1) | sed -e $MON2NUM -e 's/ ([0-9]) / 0\1 /g'} # Make sure day of the month is two digits.
|
||||||
|
echo $t(6)^'-'^$t(2)^'-'^$t(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listDir {
|
||||||
|
d=$1
|
||||||
|
dirfilter=$saveddf
|
||||||
|
if(test -f $d/_werc/config)
|
||||||
|
. $d/_werc/config
|
||||||
|
|
||||||
|
if(~ $#perm_redir_to 0) {
|
||||||
|
echo '<ul class="sitemap-list">'
|
||||||
|
|
||||||
|
for(i in `{ls -dF $d^*/ $d^*.md $d^*.html $d^*.txt >[2]/dev/null | sed $dirfilter}) {
|
||||||
|
desc=`{get_file_title $i}
|
||||||
|
u=`{echo $i|sed 's!'$sitedir'!!; '$dirclean's!/index$!/!; '}
|
||||||
|
if(! ~ $#desc 0 && ! ~ $desc '')
|
||||||
|
desc=' - '$"desc
|
||||||
|
n=`{echo /$u|sed 's/[\-_]/ /g; s,.*/([^/]+)/?$,\1,'}
|
||||||
|
echo '<li><a href="'$u'">'^$"n^'</a>' $"desc '</li>'
|
||||||
|
echo $base_url^$u >> $tmpfile
|
||||||
|
echo '<url><loc>'$base_url^$u'</loc><lastmod>'^`{get_mdate $i}^'</lastmod></url>' >> $tmpfilex
|
||||||
|
if(test -d $i)
|
||||||
|
@{ listDir $i }
|
||||||
|
}
|
||||||
|
echo '</ul>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fltr_cache listDir $sitedir/
|
||||||
|
|
||||||
|
if(test -s $tmpfile) {
|
||||||
|
mv $tmpfile $sitedir/sitemap.txt &
|
||||||
|
}
|
||||||
|
if not if(test -f $tmpfile)
|
||||||
|
rm $tmpfile
|
||||||
|
|
||||||
|
if(test -s $tmpfilex) {
|
||||||
|
{
|
||||||
|
echo '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
|
||||||
|
|
||||||
|
cat $tmpfilex
|
||||||
|
rm $tmpfilex &
|
||||||
|
echo '</urlset>'
|
||||||
|
# TODO Enable automaic search engine update notification.
|
||||||
|
#hget 'http://google.com/ping?sitemap='^`{url_encode $base_url'/sitemap.gz'} > /dev/null
|
||||||
|
|
||||||
|
} | gzip > $sitedir/sitemap.gz &
|
||||||
|
#} > $sitedir/sitemap.xml &
|
||||||
|
}
|
||||||
|
if not if(test -f $tmpfilex)
|
||||||
|
rm $tmpfilex
|
||||||
|
|
||||||
|
%}
|
Loading…
Reference in a new issue