summaryrefslogtreecommitdiff
path: root/bin/corehandlers.rc
blob: 294b1a7e56a10a9ae392b681221fa6ff6df7a2f4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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\">&raquo;<i> " bname "</i></a></li>"
        else 
            print "<li><a href=\"" path "\">&rsaquo; " 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/</\&lt;/g; s/>/\&gt;/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-) }