2016年8月13日土曜日

Apache のサーバサイドインクルードの展開

ApacheのSSIを使っていたサイトをフラットなHTMLに置き換えるためのスクリプト。
include, echo, set に対応している。つもり。
> python expand.py < input.shtml > output.html
のようにして使う。
import sys, os, re

setPattern=re.compile('<!--#set\s+var=\"(\w*)\"\s+value\s*=\s*\"(.*)\"\s*-->')
includePattern=re.compile('<!--#include\s+file=\"(.*)\"\s*-->')
echoPattern=re.compile('<!--#echo\s+var=\"(\w*)\"\s*-->')
refPattern=re.compile('\$\{(.*)\}')

def include(filename, env, outs):
    m = refPattern.search(filename)
    if m:
        if m.group(1) in env:
            filename = re.sub(refPattern, env[m.group(1)], filename)
        else:
            print "env does not have", m.group(1)
            sys.exit(0)
    with file(filename) as ins:
        process(ins, outs, env)

def echo(line, varname, env, outs):
    if not varname in env:
        print "env does not have", varname
        sys.exit(0)
    line = re.sub(echoPattern, env[varname], line)
    outs.write(line)

def process(ins, outs, env):
    for line in ins:
        stripped = line.strip()
        ms = setPattern.search(stripped)
        mi = includePattern.search(stripped)
        me = echoPattern.search(stripped)
        if ms:
            env[ms.group(1)] = ms.group(2)
        elif mi:
            include(mi.group(1), env, outs)
        elif me:
            echo(line, me.group(1), env, outs)
        else:
            outs.write(line)

def main(ins, outs):
    process(ins, outs, {})


if __name__ == "__main__":
    main(sys.stdin, sys.stdout)