feat: start keeping track of atomic changes on top of werc-1.5.0
This commit is contained in:
commit
f1486586ea
79
README
Normal file
79
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
apps/blagh/app.rc
Normal file
142
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
apps/blagh/atom.tpl
Normal file
58
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
apps/blagh/convert.rc
Executable file
20
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
apps/blagh/jsonfeed.tpl
Normal file
35
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
apps/blagh/new_post.tpl
Normal file
11
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
apps/blagh/rss20.tpl
Normal file
43
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
apps/bridge/app.rc
Executable file
103
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
apps/bridge/comments_list.tpl
Executable file
13
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
apps/bridge/foot.tpl
Executable file
37
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
apps/dirdir/app.rc
Executable file
40
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
apps/dirdir/edit.tpl
Executable file
25
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
apps/dirdir/sidebar_controls.tpl
Executable file
3
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
apps/duckduckgo/HOWTO
Normal file
20
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
apps/duckduckgo/app.rc
Executable file
30
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
apps/duckduckgo/footer.inc.sample
Normal file
3
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
apps/hello/app.rc
Executable file
10
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
apps/paste/app.rc
Executable file
45
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
apps/wman/app.rc
Executable file
89
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
apps/wman/man_page.tpl
Executable file
3
apps/wman/man_page.tpl
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
<pre>
|
||||||
|
% wman_page_gen $wman_page_file
|
||||||
|
</pre>
|
11
apps/wman/page_list.tpl
Executable file
11
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
apps/wman/search.tpl
Executable file
20
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
apps/wman/section_list.tpl
Executable file
11
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
bin/aux/addwuser.rc
Executable file
33
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
bin/aux/bpst.rc
Executable file
64
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
bin/aux/gensitemaptxt.rc
Executable file
14
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
bin/aux/runtsts.rc
Executable file
16
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
bin/cgilib.rc
Executable file
236
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
bin/contrib/fix-rc-scripts
Executable file
27
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
bin/contrib/hgweb.config
Executable file
12
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
bin/contrib/hgwebdir.cgi
Executable file
47
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
bin/contrib/markdown.pl
Executable file
1447
bin/contrib/markdown.pl
Executable file
File diff suppressed because it is too large
Load Diff
427
bin/contrib/md2html.awk
Executable file
427
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
bin/contrib/rc-httpd/handlers/authorize
Executable file
6
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
bin/contrib/rc-httpd/handlers/cgi
Executable file
46
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
bin/contrib/rc-httpd/handlers/dir-index
Executable file
111
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
bin/contrib/rc-httpd/handlers/error
Executable file
43
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
bin/contrib/rc-httpd/handlers/redirect
Executable file
30
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
bin/contrib/rc-httpd/handlers/serve-static
Executable file
43
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
bin/contrib/rc-httpd/handlers/static-or-cgi
Executable file
14
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
bin/contrib/rc-httpd/handlers/static-or-index
Executable file
5
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
bin/contrib/rc-httpd/lib/urldecode.awk
Executable file
39
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
|
||||||
|
}
|
102
bin/contrib/rc-httpd/rc-httpd
Executable file
102
bin/contrib/rc-httpd/rc-httpd
Executable file
|
@ -0,0 +1,102 @@
|
||||||
|
#!/bin/rc
|
||||||
|
rc_httpd_dir=/home/sl/www/werc/bin/contrib/rc-httpd
|
||||||
|
libdir = $rc_httpd_dir/lib
|
||||||
|
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{ dd -bs 1 -count $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;\?.*;;'}
|
||||||
|
location=`{echo $location | sed '
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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
bin/contrib/rc-httpd/select-handler
Executable file
20
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=/home/sl/www/werc/sites/$SERVER_NAME
|
||||||
|
exec static-or-cgi /home/sl/www/werc/bin/werc.rc
|
||||||
|
}
|
||||||
|
if not
|
||||||
|
error 503
|
7
bin/contrib/tcp80
Executable file
7
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
bin/contrib/urldecode.awk
Executable file
39
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
bin/contrib/urlencode.awk
Executable file
126
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
bin/contrib/webserver.rc
Executable file
30
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
bin/corehandlers.rc
Executable file
152
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
bin/fltr_cache.rc
Executable file
37
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
bin/template.awk
Executable file
55
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
bin/werc.rc
Executable file
138
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
bin/werc_errlog_wrap.rc
Executable file
5
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
bin/wercconf.rc
Executable file
19
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
bin/werclib.rc
Executable file
393
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 {
|
||||||
|
#
|
||||||
|
#}
|
39
etc/initrc
Executable file
39
etc/initrc
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
# 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)
|
||||||
|
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
etc/users/GROUP_AND_USER_ACCOUNTS
Normal file
1
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.
|
3
lib/404.tpl
Normal file
3
lib/404.tpl
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>The requested document at '<i>%($base_url$"req_path%)</i>' doesn't exist</h1>
|
||||||
|
<h4>Or take a look at the <a href="/sitemap">sitemap</a>.</h4>
|
||||||
|
<hr>
|
26
lib/default_master.tpl
Normal file
26
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>
|
7
lib/footer.inc
Normal file
7
lib/footer.inc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<div><a href="http://werc.cat-v.org/">Powered by werc</a></div>
|
||||||
|
|
||||||
|
<div><a href="/_users/login">User Login</a>
|
||||||
|
<!-- TODO: add duckduckgo site search
|
||||||
|
<form action="/_search" method=get><input type=text name=q />
|
||||||
|
-->
|
||||||
|
</div>
|
29
lib/headers.tpl
Normal file
29
lib/headers.tpl
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<!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">
|
||||||
|
|
||||||
|
% 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>
|
||||||
|
|
15
lib/top_bar.inc
Normal file
15
lib/top_bar.inc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<div>
|
||||||
|
<a href="http://gsoc.cat-v.org">gsoc</a> |
|
||||||
|
<a href="http://doc.cat-v.org">doc archive</a> |
|
||||||
|
<a href="http://repo.cat-v.org">software repo</a> |
|
||||||
|
<a href="http://ninetimes.cat-v.org">ninetimes</a> |
|
||||||
|
<a href="http://harmful.cat-v.org">harmful</a> |
|
||||||
|
<a href="http://9p.cat-v.org/">9P</a> |
|
||||||
|
<a href="http://cat-v.org">cat-v.org</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a href="http://cat-v.org/update_log">site updates</a> |
|
||||||
|
<a href="/sitemap">site map</a>
|
||||||
|
</div>
|
||||||
|
|
BIN
pub/default_favicon.ico
Executable file
BIN
pub/default_favicon.ico
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
pub/style/imgs/sgl.png
Executable file
BIN
pub/style/imgs/sgl.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
292
pub/style/sinorca-screen-alt.css
Executable file
292
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;
|
||||||
|
}
|
11
pub/style/style.css
Normal file
11
pub/style/style.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
body { display: flex; flex-wrap: wrap; font-family: sans; }
|
||||||
|
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; }
|
||||||
|
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 }
|
||||||
|
footer { display: flex; justify-content: space-between; }
|
330
pub/style/style.werc140.css
Executable file
330
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
pub/style/style_old.css
Executable file
330
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
sites/CREATE-SITE-DIRECTORIES-HERE
Normal file
0
sites/CREATE-SITE-DIRECTORIES-HERE
Normal file
5
sites/default.cat-v.org/_werc/lib/footer.inc
Normal file
5
sites/default.cat-v.org/_werc/lib/footer.inc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<br class="doNotDisplay doNotPrint" />
|
||||||
|
|
||||||
|
<div style="margin-right: auto;"><a href="http://werc.cat-v.org">Powered by werc</a></div>
|
||||||
|
|
||||||
|
<div><form action="/_search/" method="POST"><input type="text" id="searchtext" name="q"> <input type="submit" value="Search"></form></div>
|
23
sites/default.cat-v.org/_werc/lib/top_bar.inc
Normal file
23
sites/default.cat-v.org/_werc/lib/top_bar.inc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<div class="left">
|
||||||
|
<a href="http://quotes.cat-v.org">quotes</a> |
|
||||||
|
<a href="http://doc.cat-v.org">docs</a> |
|
||||||
|
<a href="http://repo.cat-v.org">repo</a> |
|
||||||
|
<a href="http://go-lang.cat-v.org">golang</a> |
|
||||||
|
<a href="http://sam.cat-v.org">sam</a> |
|
||||||
|
<a href="http://man.cat-v.org">man</a> |
|
||||||
|
<a href="http://acme.cat-v.org">acme</a> |
|
||||||
|
<a href="http://glenda.cat-v.org">Glenda</a> |
|
||||||
|
<a href="http://ninetimes.cat-v.org">9times</a> |
|
||||||
|
<a href="http://harmful.cat-v.org">harmful</a> |
|
||||||
|
<a href="http://9p.cat-v.org/">9P</a> |
|
||||||
|
<a href="http://cat-v.org">cat-v.org</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
|
||||||
|
<span class="doNotDisplay">Related sites:</span>
|
||||||
|
| <a href="http://cat-v.org/update_log">site updates</a>
|
||||||
|
| <a href="/sitemap">site map</a> |
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
2
sites/tst.cat-v.org/_werc/config
Normal file
2
sites/tst.cat-v.org/_werc/config
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
masterSite=default.cat-v.org
|
||||||
|
siteTitle='Werc Test Suite'
|
3
sites/tst.cat-v.org/apps/blagh/_werc/config
Normal file
3
sites/tst.cat-v.org/apps/blagh/_werc/config
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
conf_enable_blog
|
||||||
|
conf_blog_pubsubdub_hub='http://pubsubhubbub.appspot.com/'
|
||||||
|
|
1
sites/tst.cat-v.org/apps/bridge/a/_werc/config
Normal file
1
sites/tst.cat-v.org/apps/bridge/a/_werc/config
Normal file
|
@ -0,0 +1 @@
|
||||||
|
conf_enable_comments -a
|
4
sites/tst.cat-v.org/index.md
Normal file
4
sites/tst.cat-v.org/index.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Werc Test Suite
|
||||||
|
===============
|
||||||
|
|
||||||
|
This site contants sample/test content for the werc web anti-framework.
|
3
sites/tst.cat-v.org/titles/dashed-title.md
Normal file
3
sites/tst.cat-v.org/titles/dashed-title.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
This page has an all-lower case dashed title.
|
||||||
|
|
||||||
|
The correct page title should be: `Dashed Title`.
|
3
sites/tst.cat-v.org/titles/under_title.md
Normal file
3
sites/tst.cat-v.org/titles/under_title.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
This page has an all-lower case underscore separated title.
|
||||||
|
|
||||||
|
The correct page title should be: `Under Title`.
|
7
sites/werc.cat-v.org/_werc/config
Normal file
7
sites/werc.cat-v.org/_werc/config
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
masterSite=default.cat-v.org
|
||||||
|
siteTitle='werc'
|
||||||
|
siteSubTitle='Bringing minimalism and sanity to the web'
|
||||||
|
conf_enable_comments
|
||||||
|
conf_enable_wiki
|
||||||
|
|
||||||
|
#ll_add handlers_body_head echo '<div style="text-align:right"><script type="text/javascript" src="http://www.reddit.com/r/programming/button.js?t=1"></script></div>'
|
11
sites/werc.cat-v.org/apps/_footer.md
Normal file
11
sites/werc.cat-v.org/apps/_footer.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
External Apps
|
||||||
|
=============
|
||||||
|
|
||||||
|
This are some apps developed by werc users, to install them put them in your werc's `apps/` dir and enable them from any config file as usual.
|
||||||
|
|
||||||
|
* [Xibit](https://web.archive.org/web/20111231181538/http://xibit.soul9.org/): an image gallery app by written by soul9.
|
||||||
|
* [SMAK](https://web.archive.org/web/20091231051800/http://www.anarchyinthetubes.com/hg/smak/): a "very simple" image gallery by yiyus.
|
||||||
|
* [hgwerc](https://web.archive.org/web/20091106041738/http://www.anarchyinthetubes.com/hg/hgwerc/): a wrapper around the mercurial web interface to integrate it into werc sites, also by yiyus.
|
||||||
|
* [scrappydog](http://code.google.com/p/scrappydog/): A werc based online scrapbook by maht.
|
||||||
|
* [flip](https://web.archive.org/web/20120330121431/http://www.anarchyinthetubes.com/hg/flip/): A web interface to view PDFs, by yiyus.
|
||||||
|
* [barf](https://code.9front.org/hg/barf): blog, image, log, paste sites with pagination and tagging, by sl.
|
5
sites/werc.cat-v.org/apps/_header.md
Normal file
5
sites/werc.cat-v.org/apps/_header.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Werc Apps
|
||||||
|
=========
|
||||||
|
|
||||||
|
Werc includes the following 'apps' by default that any site can enable usually by executing a function of the form `conf_enable_myapp` in any given `_werc/config` file.
|
||||||
|
|
59
sites/werc.cat-v.org/apps/blagh/index.md
Normal file
59
sites/werc.cat-v.org/apps/blagh/index.md
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
Blagh - A Blogging engine for people who hate blogs
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Blagh is a werc app that implements a blogging engine.
|
||||||
|
|
||||||
|
Some features include:
|
||||||
|
|
||||||
|
* File based, database free.
|
||||||
|
* History browsing.
|
||||||
|
* Atom, JSON, and RSS feeds.
|
||||||
|
* Server-side feed 'aggregation' (merge multiple blogs into a single one).
|
||||||
|
* Comments using [bridge](../bridge/)
|
||||||
|
* Markdown formatting.
|
||||||
|
|
||||||
|
Possible alternative names: Blag, Blah, Bragg.
|
||||||
|
|
||||||
|
Posting
|
||||||
|
-------
|
||||||
|
|
||||||
|
New pots can be created in at least two different ways: using the web interface (if you have logged in and your user or groups are in `$conf_blog_editors`) or from the command line using the script at `bin/aux/bpst.rc`. This script will, optionally, take a file as an argument using the `-f` switch. It will open that file in your `$EDITOR` or create a new temporary file if the `-f` switch is omitted. When you have finished editing the file, the script will call `ispell` (so you may want to install that as well) to check for spelling errors. Once that has completed a new directory structure will be created in your blog's root directory as a hidden folder named after the current year (as detected by `date`). You can inspect this directory structure for continuity and `mv` it to unhide it when you are satisfied. You are encouraged to read the source of that very simple script, and you shall see that it is trivial to create new posts by simply using `mkdir` and `echo`.
|
||||||
|
|
||||||
|
Configuration options
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This are options you can set in your _werc/config
|
||||||
|
|
||||||
|
### `conf_enable_blog` *[blog dirs]*
|
||||||
|
|
||||||
|
Setup a blog in this dir. By default the blog contents will only include posts stored in this dir, if you pass any arguments the posts in the various dirs will be aggregated in this feed.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
# This will setup a blog in this dir that includes only posts in this dir.
|
||||||
|
conf_enable_blog
|
||||||
|
|
||||||
|
# This will create a blog that aggregates all the posts in all blog dirs in any users/ sub dir.
|
||||||
|
conf_enable_blog users/*/blog
|
||||||
|
|
||||||
|
### `conf_blog_editors`=(*groups or users that will be allowed to make new blog posts*)
|
||||||
|
|
||||||
|
This is optional and by default set to the 'blog-editors' group.
|
||||||
|
|
||||||
|
### `conf_max_lines_per_post=`*[integer]*
|
||||||
|
|
||||||
|
This option may be added using the patch linked bellow. It defaults to `7` which **should** only include the page heading and the first two paragraphs of each post on the main blogroll(?) page. This makes many assumptions that should be noted. It just removes everything from `conf_max_lines_per_post` to the end of the file. Traditionally, line 1 is the H1 title and line 2 is the line of = required to tell mardown of it's importance. This then assumes that each paragraph is on a single line, which is not enforced by markdown. See it in action at <http://blog.senet.us>
|
||||||
|
|
||||||
|
[blagh-91a4597480a7-conf\_max\_lines\_per\_post.diff](https://gist.github.com/anjandev/c517e79042148c136b98334867c545d8) (1.2K) (20100114)
|
||||||
|
|
||||||
|
**Author:** A Momi <anjan@momi.ca>
|
||||||
|
|
||||||
|
See also:
|
||||||
|
|
||||||
|
* To edit blog posts you can use the functionality provided by [the dirdir app](../dirdir/).
|
||||||
|
* Commenting can be handled by [the bridge app](../bridge/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
13
sites/werc.cat-v.org/apps/bridge/index.md
Normal file
13
sites/werc.cat-v.org/apps/bridge/index.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Bridge
|
||||||
|
======
|
||||||
|
|
||||||
|
Bridge is a comments/forum application for werc, which lets people post comments related to any existing document/element.
|
||||||
|
|
||||||
|
|
||||||
|
Configuration options
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### `conf_enable_comments` [-n] [*users and groups allowed to comment*]
|
||||||
|
|
||||||
|
This will enable comments in this directory and all sub-directories. `-n` enables commenting by unregistered users (their posts will be set aside for review and approval by administrators).
|
||||||
|
|
48
sites/werc.cat-v.org/apps/dirdir/index.md
Normal file
48
sites/werc.cat-v.org/apps/dirdir/index.md
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
DirDir - A directory-oriented WikiWiki
|
||||||
|
======================================
|
||||||
|
|
||||||
|
DirDir is the next generation [diri wiki](http://repo.cat-v.org/diri/), now implemented on top of werc and
|
||||||
|
taking advantage of its user, site management frameworks and other
|
||||||
|
infrastructure.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
DirDir is still somewhat experimental, but already all features diri had, plus some extras thanks to werc's power:
|
||||||
|
|
||||||
|
* Hierarchical organization.
|
||||||
|
* Markdown formatting.
|
||||||
|
* Easily customizable templates
|
||||||
|
* Simple and fine grained user permisions system.
|
||||||
|
* Completely database free.
|
||||||
|
* All needed to setup diridiri is to set a flag in your _werc/config file.
|
||||||
|
* Automatically wiki-fy existing werc documents.
|
||||||
|
* Implemented in about two dozen lines of rc scripts.
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Just login, go to any page, and click the `Edit` button.
|
||||||
|
|
||||||
|
To create a new page, go to the address where you want to create the new page, click `Edit`, enter the initial contents, `Save`, and you are done.
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
Mostly usable, all basic features already implemented in the latest werc source
|
||||||
|
tree.
|
||||||
|
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
|
||||||
|
* Do some markdown preprocessing, for example: `[[Foo Bar]]` -> `[Foo Bar](foo-bar)`
|
||||||
|
|
||||||
|
|
||||||
|
About the name
|
||||||
|
--------------
|
||||||
|
|
||||||
|
DirDir is a pun on its predecessor diri and WikiWiki, and [Dirdir is also the title of a novel](http://www.amazon.com/gp/product/0879974788?ie=UTF8&tag=catv-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0879974788) by science fiction and literature grand master [Jack Vance](http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2Fs%3Fie%3DUTF8%26redirect%3Dtrue%26search-type%3Dss%26index%3Dbooks%26ref%3Dntt%255Fathr%255Fdp%255Fsr%255F1%26field-author%3DJack%2520Vance&tag=catv-20&linkCode=ur2&camp=1789&creative=39095).
|
||||||
|
|
39
sites/werc.cat-v.org/apps/duckduckgo/index.md
Normal file
39
sites/werc.cat-v.org/apps/duckduckgo/index.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
duckduckgo - Simple sitesearch using DuckDuckGo.com
|
||||||
|
===================================
|
||||||
|
|
||||||
|
duckduckgo is a very simple app that allows you to redirect a path
|
||||||
|
(by default /_search/) to a query to duckduckgo.com restricted to
|
||||||
|
your site.
|
||||||
|
|
||||||
|
Currently, to change that path requires editing the app. In the
|
||||||
|
future, the path will be a configuration option.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
First, create the search path and the _werc directory under it:
|
||||||
|
|
||||||
|
mkdir -p /www/werc/sites/MYSITE/_search/_werc/
|
||||||
|
|
||||||
|
Then, enable the duckduckgo app in that directory:
|
||||||
|
|
||||||
|
echo 'conf_enable_duckduckgo' > /www/werc/sites/MYSITE/_search/_werc/config
|
||||||
|
|
||||||
|
Next, deploy the search form somewhere on your site. This example puts
|
||||||
|
it in your footer:
|
||||||
|
|
||||||
|
mkdir -p /www/werc/sites/MYSITE/_werc/lib/
|
||||||
|
cp /www/werc/apps/search/footer.inc.sample /www/werc/sites/MYSITE/_werc/lib/footer.inc
|
||||||
|
|
||||||
|
Demo
|
||||||
|
----
|
||||||
|
|
||||||
|
For a demo of this app, see the footer of your favorite cat-v.org site.
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
|
||||||
|
* 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
|
||||||
|
|
34
sites/werc.cat-v.org/apps/wman/index.md
Normal file
34
sites/werc.cat-v.org/apps/wman/index.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
wman - A Web Interface to Man Pages
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Wman is an app that allows you to export Unix and Plan 9-style man pages. It
|
||||||
|
can do this directly, without need to generate static html versions and will
|
||||||
|
automatically pick updates and new man pages.
|
||||||
|
|
||||||
|
It is also fairly smart in generating links for man page references.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
To display a collection of man pages in a desired path you can use the following config directive:
|
||||||
|
|
||||||
|
conf_enable_wman /usr/share/man
|
||||||
|
|
||||||
|
This will allow you to browse the man pages under /usr/share/man.
|
||||||
|
|
||||||
|
For man pages organized in the traditional unix structure `manN/foo.N` where N is the section number, set in your config file:
|
||||||
|
|
||||||
|
wman_unix_mode=1
|
||||||
|
|
||||||
|
Demo
|
||||||
|
----
|
||||||
|
|
||||||
|
For a demo of this app see [man.cat-v.org](http://man.cat-v.org).
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
|
||||||
|
* We don't handle compressed man pages, but this should be trivial to add.
|
||||||
|
* Unix systems might use different macros for their man pages.
|
||||||
|
* Search (using keywords? Google? grep?)
|
||||||
|
* Inferno contains man pages named like 'foo-0intro', which are refered as foo-intro(X), should automatically add (or remove) the extra '0' (Examples: sys-intro(2) and draw-intro(2)).
|
21
sites/werc.cat-v.org/development/index.md
Normal file
21
sites/werc.cat-v.org/development/index.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Werc Development
|
||||||
|
================
|
||||||
|
|
||||||
|
The latest dev code is available in the werc mercurial repo: <https://code.9front.org/hg/werc>
|
||||||
|
|
||||||
|
|
||||||
|
Version Numbering and Branching Rules
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
There is no such thing! Originally a convention similar to that of the Linux kernel was used, but it is easier to do incremental work on a single branch.
|
||||||
|
|
||||||
|
For radical or experimental changes the `werc-dev` branch might be used, but at the moment it is outdated.
|
||||||
|
|
||||||
|
Bug reports, feature requests, bug fixes and other patches are all very welcome, just send them to the [werc mailing list](http://lists.9front.org).
|
||||||
|
|
||||||
|
|
||||||
|
See Also
|
||||||
|
--------
|
||||||
|
|
||||||
|
* The [Roadmap](roadmap).
|
||||||
|
* [TODO](todo) list.
|
67
sites/werc.cat-v.org/development/roadmap.md
Normal file
67
sites/werc.cat-v.org/development/roadmap.md
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
Development Roadmap
|
||||||
|
===================
|
||||||
|
|
||||||
|
The versioning scheme is a mess, originally even minor version numbers were
|
||||||
|
supposed to be stable and odd ones development branches, but turns out that for
|
||||||
|
the most part it is easier to do incremental development instead of keeping
|
||||||
|
'dev' and 'stable' branches.
|
||||||
|
|
||||||
|
A development branch might be added in the future if the changes are radical
|
||||||
|
enough and break backwards compatibility in some important way. For this the
|
||||||
|
deprecated and currently outdated `werc-dev` mercurial repo will be used.
|
||||||
|
|
||||||
|
|
||||||
|
Werc 1.5.x, current stable branch
|
||||||
|
----------
|
||||||
|
|
||||||
|
Planned major changes in 1.5
|
||||||
|
|
||||||
|
* <strike>Include required p9p binaries in standard distribution (or with some easy to deploy packaging).</strike>
|
||||||
|
* New/rewritten css layout, using html5 flexbox [*Done*]
|
||||||
|
* File upload support [*Code contributed by maht, needs integration*]
|
||||||
|
* OpenID support [*Code contributed by maht, also needs integration*]
|
||||||
|
* More complete test suite. [*See: <http://tst.cat-v.org>*]
|
||||||
|
* Integrate all changes from 9front live sites [*Done*]
|
||||||
|
* Add rc-httpd [*Done*]
|
||||||
|
* Add optional headers.tpl to site-specific templates in _werc/lib/ [*Done*]
|
||||||
|
* Add apps/mdir [*Code contributed by khm, needs integration*]
|
||||||
|
* Add apps/paste [*Code contributed by khm, rewrite to use apps/upload*]
|
||||||
|
|
||||||
|
|
||||||
|
Werc 1.4.x, previous stable branch
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
* Mostly bugfixes, documentation work, and minor improvements.
|
||||||
|
|
||||||
|
|
||||||
|
Werc 1.2.x
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Only security fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Werc 1.1.x dev branch
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* Convert all templates and pages to HTML 5. [*Done*]
|
||||||
|
* Include new markdown implementation in pure awk by yuyis.[*Done*]
|
||||||
|
* Native Plan 9 httpd works out of the box. [*Mostly done*]
|
||||||
|
* Support for Google's Pubsubhubbub. [*Experimental implementation already done*]
|
||||||
|
* Include test suite/site (also to be hosted at http://tst.cat-v.org) [*In Progress*]
|
||||||
|
|
||||||
|
|
||||||
|
Werc 1.0.x
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Abandoned, please upgrade.
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
Werc 2.0 Plans
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* Big redesigns / rewrites.
|
||||||
|
* Any non-backwards compatible changes.
|
||||||
|
* Bring some sanity to the function/config-variable naming insanity.
|
||||||
|
* Nothing else planned yet.
|
88
sites/werc.cat-v.org/development/todo.md
Normal file
88
sites/werc.cat-v.org/development/todo.md
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
Plans and Ideas for the Future
|
||||||
|
==============================
|
||||||
|
|
||||||
|
This page lists various assorted ideas and features that have been proposed at
|
||||||
|
some point or another, nothing (except fixing the listed bugs) is assured to be
|
||||||
|
implemented, many things here might turn out to be bad ideas.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Review ideas from: http://www.w3.org/TR/chips/ and http://www.w3.org/Provider/Style/URI and see if we can do better.
|
||||||
|
* Canonize and redirect all requests, we already do this for things like missing or trailing /, should do the same for /. and /./, etc. Deleting trailing . and , should make pasted urls in emails work as links (**Mostly done in RC1**)
|
||||||
|
* Blog:
|
||||||
|
* Comment threading.
|
||||||
|
* Some form of pagination (taking advantage of history browsing.) (**Partially done**)
|
||||||
|
* Sitemaps:
|
||||||
|
* Index pages should be used for description of directories.
|
||||||
|
* Cache web sitemap generation. (**Done in RC0**)
|
||||||
|
* Layout improvements:
|
||||||
|
* Need to find a way to rig the order of items in the sidebar.
|
||||||
|
* Right sidebar.
|
||||||
|
* Top+left/right nav vars (breadcrumbs at the top, current dir listing on the side)
|
||||||
|
* Make it easier to disable all sidebars and headers/footers, eg., for full screen mode.
|
||||||
|
* More testing and optimizations for mobile browsers, eg., http://www.operamini.com/demo/ Left sidebar had some minor issues in cellphones at some point.
|
||||||
|
* Better page titles (include whole path hierarchy?) (**Partially done, is it good enough now?**)
|
||||||
|
* Allow utf-8 characters in path elements (need to make sure this is safe, and not sure how useful it will be)
|
||||||
|
* General code:
|
||||||
|
* Write a regression test suite. (*Started*)
|
||||||
|
* Replace all references to non p9p/p9 programs (*Done?*)
|
||||||
|
* Document better the 'API' for sub-apps, both a set of environment vars apps can rely on (and in some cases set) and functions they can call (WIP).
|
||||||
|
* Better generation of descriptive HTML META tags, eg.,: {META name="description" content="This is the Google Summer of Code blog for Plan9 and Inferno projects."} {META name="keywords" content="google, summer of code, inferno, plan9, programming"}
|
||||||
|
* Should add werc to certain wikipedia lists:
|
||||||
|
* `http://en.wikipedia.org/wiki/List_of_content_management_systems`
|
||||||
|
* `http://en.wikipedia.org/wiki/Comparison_of_wiki_software`
|
||||||
|
* Include txt2tags as builtin alternative to markdown.
|
||||||
|
* Spam protection:
|
||||||
|
* Mathematic pseudo-CAPTCHA ala WP's 'Math Comment Spam Protection Plugin'.
|
||||||
|
* kfx (via cinap) suggests you just put a hidden text input box (or textarea?), "Dont write in this input box: [ ..... ]", if the bots fill it out ignore the post
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Future Plans and Blue Sky
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* Wanted [apps](/apps/):
|
||||||
|
* Tagging, eg., append to _werc/tags
|
||||||
|
* Related links sidebar generation.
|
||||||
|
* [Bug/issue tracking app](/apps/gregor/).
|
||||||
|
* Hg/git repository browser.
|
||||||
|
* Implement AtomPub.
|
||||||
|
|
||||||
|
* Further modularization and extensibility (meta-templates) (Is the new app framework enough for this?)
|
||||||
|
* A way to wrap external cgi applications (eg., existing hg/git browser)
|
||||||
|
* A way to generate static sites (ie., use werc as an offline templating system)
|
||||||
|
* [9P](http://9p.cat-v.org) interface.
|
||||||
|
* New (simplified) markdown implementation, ideally in C or awk (maybe smu/libsmu by gottox?), yiyus great md2html.awk is a great start!
|
||||||
|
* Simplified
|
||||||
|
* Tables
|
||||||
|
* Images
|
||||||
|
* Autogenerated anchors/navigation boxes
|
||||||
|
* No inline html
|
||||||
|
|
||||||
|
Similar frameworks to be investigated and mined for good ideas to steal:
|
||||||
|
|
||||||
|
* TinyTim: http://www.reddit.com/r/programming/duplicates/dbaee/
|
||||||
|
* nanoblogger: http://nanoblogger.sourceforge.net/
|
||||||
|
|
||||||
|
|
||||||
|
Known Bugs
|
||||||
|
----------
|
||||||
|
|
||||||
|
* It seems that certain chars are not propely encoded in cookies, possibly broken chars: :&%[+ Fix should go in cgilib.rc^set_cookie (Have to figure out the proper way to scape cookie strings first)
|
||||||
|
* If a dir under apps/ doesn't contain an app.rc file, werc fails to start. A possible fix would be to replace $werc_apps default with `apps/*/app.rc` instead of `apps/*/`, this would be backwards incompatible, but I doubt anyone uses that option.
|
||||||
|
* Links in Blagh feeds become confused if markdown 'references' are used, markdown references suck, but I guess we need to address this somehow...
|
||||||
|
* Somewhat similarly to the abouve, relative urls in imgs, links, etc. can easily break when used in Blagh posts, so it is not all markdown's fault.
|
||||||
|
* .md files of the following form, without a new line after the last = seem to cause problems in some setups:
|
||||||
|
|
||||||
|
Foo Bar
|
||||||
|
=======
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Fixed or WFM Bugs
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Sitemap can handle $dirfilter inconsistently from other places (**fixed**).
|
||||||
|
* Finding directories that are inaccessible (-rx) can generate an infinite loop (**Works for me? Fixed with new menu code?**)
|
||||||
|
* Some cat-v.org bits still left over here and there, should make them configurable (1.0 blocker) (**fixed**?)
|
1
sites/werc.cat-v.org/docs/_werc/config
Normal file
1
sites/werc.cat-v.org/docs/_werc/config
Normal file
|
@ -0,0 +1 @@
|
||||||
|
conf_perm_redirect _ -
|
68
sites/werc.cat-v.org/docs/config-options.md
Normal file
68
sites/werc.cat-v.org/docs/config-options.md
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
Werc Configuration Options
|
||||||
|
==========================
|
||||||
|
|
||||||
|
You can also find a description of some basic config options in the `etc/initrc` file itself.
|
||||||
|
|
||||||
|
General Setup Options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* `formatter` - Command to use for document formatting (usually some form of markdown), should be able to take input both from file names passed as arguments or from stdin if no file names are provided. By default: `formatter=(fltr_cache md2html.awk)`
|
||||||
|
|
||||||
|
|
||||||
|
Titles and Metadata
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Variables:
|
||||||
|
|
||||||
|
* Page title:
|
||||||
|
* siteTitle
|
||||||
|
* siteSubTitle
|
||||||
|
|
||||||
|
* Html header meta tags:
|
||||||
|
* meta_description - `<meta name="description" ...`
|
||||||
|
* meta_keywords - `<meta name="keywords" ...`
|
||||||
|
* extraHeaders - Raw extra html headers, the content of this var will be inserted inside the `<head>` tag..
|
||||||
|
|
||||||
|
|
||||||
|
Sidebar and Navigation
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Variables:
|
||||||
|
|
||||||
|
* sideBarNavTitle
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
|
||||||
|
* `conf_hide_paths [path_patterns ...]` - Hide the given patterns from navigation menu, sitemap and dir listing (do *not* depend on this for security!).
|
||||||
|
|
||||||
|
HTTP Control
|
||||||
|
------------
|
||||||
|
|
||||||
|
Variables:
|
||||||
|
|
||||||
|
* extraHttpHeaders - Raw HTTP headers to be added to response.
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
|
||||||
|
* `conf_perm_redirect [pattern] destination` - If pattern is provided, match it against the requested url, and replace the match with `destination`; ie., *s/pattern/destination/.
|
||||||
|
|
||||||
|
|
||||||
|
Access Control and Permissions
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The permissions system is very flexible, for example to only allow access to members of the group 'editors' you can do something like:
|
||||||
|
|
||||||
|
switch ($req_path) {
|
||||||
|
case /_users/login
|
||||||
|
case /pub/*
|
||||||
|
case /robots.txt
|
||||||
|
case *
|
||||||
|
if(! check_user editors)
|
||||||
|
perm_redirect /_users/login
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
To automatically redirect users without permission to the login page if they are not members of the group 'editors'.
|
||||||
|
|
||||||
|
See also [the documentation on user and group management](user_management).
|
||||||
|
|
15
sites/werc.cat-v.org/docs/css-style.md
Normal file
15
sites/werc.cat-v.org/docs/css-style.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
Custom CSS Stylesheets
|
||||||
|
=====================
|
||||||
|
|
||||||
|
If you create a file under your site's dir at _werc/pub/style.css it will be included automatically after the standard werc stylesheet.
|
||||||
|
|
||||||
|
You can copy pub/style/style.css and customize it, or you can take a simpler file and just change the main color theme.
|
||||||
|
|
||||||
|
Here is an example of how to set the main werc colors:
|
||||||
|
|
||||||
|
|
||||||
|
header nav { background-color: rgb(100,135,220); color: white; }
|
||||||
|
header h1 { background-color: #ff6d06; color: black; }
|
||||||
|
body > nav > div { border-bottom: 1px solid #ddd; }
|
||||||
|
body > nav > div a { color: rgb(0, 102, 204); }
|
||||||
|
body > nav > div a:hover { color: white; background-color: rgb(100,135,220); }
|
29
sites/werc.cat-v.org/docs/dir-listings.md
Normal file
29
sites/werc.cat-v.org/docs/dir-listings.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
Autogenerated Directory Listings
|
||||||
|
================================
|
||||||
|
|
||||||
|
If a directory has no `index.md`, `index.html` or `index.txt` and has no other
|
||||||
|
*main handler* set up by a [werc app](/apps/), the default directory listing
|
||||||
|
handler is used.
|
||||||
|
|
||||||
|
The default directory handler simply displays the path to the directory, and a
|
||||||
|
list of links to all files and dirs located at this path.
|
||||||
|
|
||||||
|
|
||||||
|
Header and footer
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
If a `_header.md` or `_footer.md` files are found in the directory, their
|
||||||
|
contents will be displayed in the corresponding sections before and after
|
||||||
|
the directory contents.
|
||||||
|
|
||||||
|
|
||||||
|
Tuning the item's order
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
You can set the `dir_listing_ls_opts` config variable in the dir's corresponding _werc/config to change the way items will be ordered.
|
||||||
|
|
||||||
|
For example to list items in reverse chronological order simply add:
|
||||||
|
|
||||||
|
dir_listing_ls_opts=( -t )
|
||||||
|
|
||||||
|
The options taken are [the standard Plan 9 ls(1) flags](http://man.cat-v.org/plan_9/1/ls).
|
56
sites/werc.cat-v.org/docs/rc-template-lang.md
Normal file
56
sites/werc.cat-v.org/docs/rc-template-lang.md
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
The Rc Template Language
|
||||||
|
========================
|
||||||
|
|
||||||
|
Implemented by Kris, thanks!
|
||||||
|
|
||||||
|
Basic syntax:
|
||||||
|
|
||||||
|
* Lines starting with % are executed as rc commands, the resulting output is inserted in the document.
|
||||||
|
* use %{ and %} to delimit multi line sections of rc code (note the lack of space between % and { or }!
|
||||||
|
* To 'inline' the value of an environment variable use `%($my_var%)`
|
||||||
|
|
||||||
|
That is basically it!
|
||||||
|
|
||||||
|
For further documentation on rc see:
|
||||||
|
|
||||||
|
* [The rc(1) man page from Plan 9](http://man.cat-v.org/plan_9/1/rc).
|
||||||
|
* [The rc shell paper by Tom Duff](http://rc.cat-v.org).
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Loops
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
% for(i in a b c) {
|
||||||
|
% echo '<li>'$i'</li>'
|
||||||
|
% }
|
||||||
|
</uL>
|
||||||
|
|
||||||
|
Can also be writen as:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
%{
|
||||||
|
for(i in a b c) {
|
||||||
|
echo '<li>'$i'</li>'
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
</uL>
|
||||||
|
|
||||||
|
and is equivalent to:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
% for(i in a b c) {
|
||||||
|
<li>%($i%)</li>
|
||||||
|
% }
|
||||||
|
</uL>
|
||||||
|
|
||||||
|
All three code examples result in this output:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>a</li>
|
||||||
|
<li>b</li>
|
||||||
|
<li>c</li>
|
||||||
|
</ul>
|
||||||
|
|
54
sites/werc.cat-v.org/docs/site-customization.md
Normal file
54
sites/werc.cat-v.org/docs/site-customization.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
Site Customization
|
||||||
|
==================
|
||||||
|
|
||||||
|
To change any of the default templates or include files found in /lib/ simply copy them from /lib/ to your site's _werc/lib/ and edit at will.
|
||||||
|
|
||||||
|
To change any of the templates found in /tpl/ (e.g. sitemap.tpl), copy the file to your site's root (e.g. /sites/foo.bar.com/sitemap.tpl) and then edit.
|
||||||
|
|
||||||
|
File Types
|
||||||
|
----------
|
||||||
|
|
||||||
|
* '.tpl' files are rc [template files](rc_template_lang).
|
||||||
|
* '.inc' are text files that are inserted 'as is' without any extra processing.
|
||||||
|
|
||||||
|
Site Groups
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Site configuration and customization and be 'grouped' to allow a shared set of templates among a specific group of sites (useful for sets of sub-domains for example).
|
||||||
|
|
||||||
|
Simply set 'masterSite' configuration variable to the name of the site you want to 'inherit' templates, style and configuration from.
|
||||||
|
|
||||||
|
For example, if we have two sites bar.com and foo.bar.com, and in sites/foo.bar.com/_werc/conf we add:
|
||||||
|
|
||||||
|
masterSite=bar.com
|
||||||
|
|
||||||
|
When a template (eg., 404.tpl) is requested it will be looked up first in /sites/foo.bar.com/_werc/lib/404.tpl, if that fails then in /sites/bar.com/_werc/lib/, and if that is missing too, the default /lib/404.tpl is used.
|
||||||
|
|
||||||
|
The same applies to .inc files.
|
||||||
|
|
||||||
|
|
||||||
|
List of Template and Included Files
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Here is a list of the most commonly used templates and include files with their corresponding descriptions.
|
||||||
|
|
||||||
|
Include:
|
||||||
|
|
||||||
|
* top_bar.inc: The thin header at the top of every page, usually contains static links to other related sites or anything else you like.
|
||||||
|
* footer.inc: Similar but at the bottom of every page, by default includes a link to the user login page.
|
||||||
|
* headers.inc: Raw html headers to be included inside <head> tag.
|
||||||
|
|
||||||
|
Templates:
|
||||||
|
|
||||||
|
* default_master.tpl: This is the main template, which calls all the sidebar and other handlers and applications, usually you won't need to edit it unless you want to make changes to the layout or similar dramatic changes.
|
||||||
|
* headers.tpl: Template for the default headers.
|
||||||
|
* sitemap.tpl: Template for the sitemap page.
|
||||||
|
* 404.tpl: Template for 'File Not Found' pages.
|
||||||
|
|
||||||
|
|
||||||
|
See also
|
||||||
|
--------
|
||||||
|
|
||||||
|
* [CSS style sheets customization](css_style).
|
||||||
|
|
||||||
|
|
36
sites/werc.cat-v.org/docs/user-management.md
Normal file
36
sites/werc.cat-v.org/docs/user-management.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
User and Group Management
|
||||||
|
=========================
|
||||||
|
|
||||||
|
User account and group membership information are stored under `etc/users/`.
|
||||||
|
|
||||||
|
A user account consists of a directory under `etc/users/` that contains files with that users account information, the only required file is `password` containing a password for the user. For example:
|
||||||
|
|
||||||
|
% ls etc/users/
|
||||||
|
eekee uriel yosyp
|
||||||
|
% cat etc/users/uriel/password
|
||||||
|
mypass
|
||||||
|
|
||||||
|
Users and groups share the same namespace, you can create a group the same way you create a user but instead of a 'password' file adding a 'members' file containing the names of the group members, one per line.
|
||||||
|
|
||||||
|
A 'user-group' directory can contain both a password and members file, in which case it will act concurrently as a user and as a group.
|
||||||
|
|
||||||
|
The group 'admin' is 'built-in' and any members in that group will have admin privileges for most werc apps by default.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
To create a user called [glenda](http://glenda.cat-v.org) that is a member of the group `rabbits` you can do:
|
||||||
|
|
||||||
|
% mkdir etc/users/glenda/
|
||||||
|
% echo carrot > etc/users/glenda/password
|
||||||
|
% mkdir -p etc/users/rabbits
|
||||||
|
% echo glenda >> etc/users/rabbits/members
|
||||||
|
|
||||||
|
Utils
|
||||||
|
-----
|
||||||
|
|
||||||
|
The script at bin/aux/addwuser.rc allows you to even more trivially add users.
|
||||||
|
|
||||||
|
addwuser.rc user_name user_pass [groups ...]
|
||||||
|
|
||||||
|
|
16
sites/werc.cat-v.org/docs/web-server-setup/_header.md
Normal file
16
sites/werc.cat-v.org/docs/web-server-setup/_header.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
Setting Up Your HTTP Server to Run Werc
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
|
||||||
|
Werc should work with any web server that supports the CGI interface, and a few
|
||||||
|
that don't. Here are collected instructions and sample configurations for some
|
||||||
|
of the most popular HTTP servers that people has used with werc.
|
||||||
|
|
||||||
|
In general setup consists of mapping all paths for a virtual host to the
|
||||||
|
werc.rc script, usually in practice this means that the `document root` (or
|
||||||
|
similar concept) for a virtual host is mapped to
|
||||||
|
`/path/to/werc/sites/domain.name.com/`, and if no static file matches the
|
||||||
|
request, control is handed to werc.rc, this allows the HTTP server to handle
|
||||||
|
static files and werc to handle everything else (note that such a setup will
|
||||||
|
expose your `_werc/config` files, which usually should not be a security
|
||||||
|
issue).
|
93
sites/werc.cat-v.org/docs/web-server-setup/apache.md
Normal file
93
sites/werc.cat-v.org/docs/web-server-setup/apache.md
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
Setup werc with Apache
|
||||||
|
======================
|
||||||
|
|
||||||
|
Note: Apache 2.x configuration should be similar to 1.3.x, but Apache 2.x is not recommended due to unwindy complexity, please use a saner web server.
|
||||||
|
|
||||||
|
Apache 1.3.x: minimalist configuration
|
||||||
|
======================================
|
||||||
|
|
||||||
|
No virtual hosts and let werc handle static files.
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
ServerName test.cat-v.org
|
||||||
|
AddHandler cgi-script .rc
|
||||||
|
|
||||||
|
<Directory /var/www/werc/bin>
|
||||||
|
Options ExecCGI
|
||||||
|
</Directory>
|
||||||
|
<IfModule mod_dir.c>
|
||||||
|
DirectoryIndex /werc.rc
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
RewriteRule /werc.rc /var/www/werc/bin/werc.rc
|
||||||
|
DocumentRoot /var/www/werc/bin/
|
||||||
|
ErrorDocument 404 /werc.rc
|
||||||
|
|
||||||
|
|
||||||
|
Apache 1.3.x: standard configuration
|
||||||
|
====================================
|
||||||
|
|
||||||
|
This lets apache handle static files.
|
||||||
|
|
||||||
|
<VirtualHost *>
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
ServerName test.cat-v.org
|
||||||
|
AddHandler cgi-script .rc
|
||||||
|
|
||||||
|
<Directory /var/www/werc/bin>
|
||||||
|
Options ExecCGI
|
||||||
|
</Directory>
|
||||||
|
<IfModule mod_dir.c>
|
||||||
|
DirectoryIndex /werc.rc
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
RewriteRule (.*) /var/www/werc/sites/%{HTTP_HOST}/$1
|
||||||
|
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule .* /var/www/werc/bin/werc.rc
|
||||||
|
|
||||||
|
RewriteRule /werc.rc /var/www/werc/bin/werc.rc
|
||||||
|
DocumentRoot /var/www/werc/bin/
|
||||||
|
ErrorDocument 404 /werc.rc
|
||||||
|
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
||||||
|
Apache 1.3.x: advanced configuration
|
||||||
|
====================================
|
||||||
|
|
||||||
|
|
||||||
|
<VirtualHost *>
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
ServerName cat-v.org
|
||||||
|
ServerAlias www.cat-v.org harmful.cat-v.org 9p.cat-v.org gsoc.cat-v.org doc.cat-v.org uriel.cat-v.org www.binarydream.org ninetimes.cat-v.org *.cat-v.org
|
||||||
|
AddHandler cgi-script .rc
|
||||||
|
AddHandler cgi-script .cgi
|
||||||
|
<Directory /home/uriel/cat-v.org/bin>
|
||||||
|
Options ExecCGI
|
||||||
|
</Directory>
|
||||||
|
<IfModule mod_dir.c>
|
||||||
|
DirectoryIndex /werc.rc
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
RewriteRule ^/hg/(.*) /home/uriel/cat-v.org/bin/hgwebdir.cgi/$1 [L]
|
||||||
|
|
||||||
|
RewriteRule /pub/style/style.css /home/uriel/cat-v.org/pub/style/style.css [L]
|
||||||
|
RewriteRule /pub/ /home/uriel/cat-v.org/pub/ [L]
|
||||||
|
RewriteRule /favicon.ico /home/uriel/cat-v.org/pub/default_favicon.ico [L]
|
||||||
|
|
||||||
|
|
||||||
|
RewriteRule (.*) /home/uriel/cat-v.org/sites/%{HTTP_HOST}/$1
|
||||||
|
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule .* /home/uriel/cat-v.org/bin/werc.rc
|
||||||
|
|
||||||
|
RewriteRule /werc.rc /home/uriel/cat-v.org/bin/werc.rc
|
||||||
|
DocumentRoot /home/uriel/cat-v.org/bin/
|
||||||
|
ErrorDocument 404 /werc.rc
|
||||||
|
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
14
sites/werc.cat-v.org/docs/web-server-setup/cgd.md
Normal file
14
sites/werc.cat-v.org/docs/web-server-setup/cgd.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
cgd
|
||||||
|
===
|
||||||
|
|
||||||
|
Cgd is a simple daemon written in [go](http://golang.org) that can
|
||||||
|
serve a CGI script over HTTP or FastCGI. It only needs to know the
|
||||||
|
location of the Plan 9 (9base, frontbase, or plan9port) binaries, and
|
||||||
|
the location of the werc installation itself. There is no
|
||||||
|
configuration file.
|
||||||
|
|
||||||
|
For example, to run werc under cgd on Plan 9:
|
||||||
|
|
||||||
|
PLAN9=/ cgd -c $werc/bin/werc.rc -w $werc/bin
|
||||||
|
|
||||||
|
Download it here: <https://code.9front.org/hg/cgd>
|
31
sites/werc.cat-v.org/docs/web-server-setup/cherokee.md
Normal file
31
sites/werc.cat-v.org/docs/web-server-setup/cherokee.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
Configuring werc with Cherokee
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Contributed by sqweek, thanks!
|
||||||
|
|
||||||
|
Cherokee Version 0.7.1
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
vserver!default!rule!600!only_secure = 0
|
||||||
|
vserver!default!rule!600!handler = cgi
|
||||||
|
vserver!default!rule!600!handler!error_handler = 1
|
||||||
|
vserver!default!rule!600!handler!check_file = 1
|
||||||
|
vserver!default!rule!600!handler!script_alias =
|
||||||
|
/usr/local/werc/bin/werc.rc
|
||||||
|
vserver!default!rule!600!handler!pass_req_headers = 0
|
||||||
|
vserver!default!rule!600!match = directory
|
||||||
|
vserver!default!rule!600!match!directory = /code
|
||||||
|
vserver!default!rule!600!match!final = 1
|
||||||
|
|
||||||
|
|
||||||
|
Cherokee Version 0.5.3
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Directory /code {
|
||||||
|
Handler cgi {
|
||||||
|
Scriptalias /usr/local/werc/bin/werc.rc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Isn't progress wonderful?
|
16
sites/werc.cat-v.org/docs/web-server-setup/hiawatha.md
Normal file
16
sites/werc.cat-v.org/docs/web-server-setup/hiawatha.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
Hiawatha Web Server Configuration
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Contributed by sqweek, thanks!
|
||||||
|
|
||||||
|
This are the relevant bits:
|
||||||
|
|
||||||
|
CGIhandler = /usr/local/plan9/bin/rc:rc
|
||||||
|
ExecuteCGI = yes
|
||||||
|
RewriteURL = werc
|
||||||
|
UrlRewrite {
|
||||||
|
RewriteID = werc
|
||||||
|
Match ^(/code|/index|/contact|/clique).* Rewrite /werc.rc
|
||||||
|
Match ^/$ Rewrite /werc.rc
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user