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