"""Generic FAQ Wizard.

This is a CGI program that maintains a user-editable FAQ.  It uses RCS
to keep track of changes to individual FAQ entries.  It is fully
configurable; everything you might want to change when using this
program to maintain some other FAQ than the Python FAQ is contained in
the configuration module, faqconf.py.

Note that this is not an executable script; it's an importable module.
The actual script to place in cgi-bin is faqw.py.

"""

import sys, time, os, stat, re, cgi, faqconf
from faqconf import *                   # This imports all uppercase names
now = time.time()

class FileError:
    def __init__(self, file):
        self.file = file

class InvalidFile(FileError):
    pass

class NoSuchSection(FileError):
    def __init__(self, section):
        FileError.__init__(self, NEWFILENAME %(section, 1))
        self.section = section

class NoSuchFile(FileError):
    def __init__(self, file, why=None):
        FileError.__init__(self, file)
        self.why = why

def escape(s):
    s = s.replace('&', '&amp;')
    s = s.replace('<', '&lt;')
    s = s.replace('>', '&gt;')
    return s

def escapeq(s):
    s = escape(s)
    s = s.replace('"', '&quot;')
    return s

def _interpolate(format, args, kw):
    try:
        quote = kw['_quote']
    except KeyError:
        quote = 1
    d = (kw,) + args + (faqconf.__dict__,)
    m = MagicDict(d, quote)
    return format % m

def interpolate(format, *args, **kw):
    return _interpolate(format, args, kw)

def emit(format, *args, **kw):
    try:
        f = kw['_file']
    except KeyError:
        f = sys.stdout
    f.write(_interpolate(format, args, kw))

translate_prog = None

def translate(text, pre=0):
    global translate_prog
    if not translate_prog:
        translate_prog = prog = re.compile(
            r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
    else:
        prog = translate_prog
    i = 0
    list = []
    while 1:
        m = prog.search(text, i)
        if not m:
            break
        j = m.start()
        list.append(escape(text[i:j]))
        i = j
        url = m.group(0)
        while url[-1] in '();:,.?\'"<>':
            url = url[:-1]
        i = i + len(url)
        url = escape(url)
        if not pre or (pre and PROCESS_PREFORMAT):
            if ':' in url:
                repl = '<A HREF="%s">%s</A>' % (url, url)
            else:
                repl = '<A HREF="mailto:%s">%s</A>' % (url, url)
        else:
            repl = url
        list.append(repl)
    j = len(text)
    list.append(escape(text[i:j]))
    return ''.join(list)

def emphasize(line):
    return re.sub(r'\*([a-zA-Z]+)\*', r'<I>\1</I>', line)

revparse_prog = None

def revparse(rev):
    global revparse_prog
    if not revparse_prog:
        revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1,4})$')
    m = revparse_prog.match(rev)
    if not m:
        return None
    [major, minor] = map(int, m.group(1, 2))
    return major, minor

logon = 0
def log(text):
    if logon:
        logfile = open("logfile", "a")
        logfile.write(text + "\n")
        logfile.close()

def load_cookies():
    if not os.environ.has_key('HTTP_COOKIE'):
        return {}
    raw = os.environ['HTTP_COOKIE']
    words = [s.strip() for s in raw.split(';')]
    cookies = {}
    for word in words:
        i = word.find('=')
        if i >= 0:
            key, value = word[:i], word[i+1:]
            cookies[key] = value
    return cookies

def load_my_cookie():
    cookies = load_cookies()
    try:
        value = cookies[COOKIE_NAME]
    except KeyError:
        return {}
    import urllib
    value = urllib.unquote(value)
    words = value.split('/')
    while len(words) < 3:
        words.append('')
    author = '/'.join(words[:-2])
    email = words[-2]
    password = words[-1]
    return {'author': author,
            'email': email,
            'password': password}

def send_my_cookie(ui):
    name = COOKIE_NAME
    value = "%s/%s/%s" % (ui.author, ui.email, ui.password)
    import urllib
    value = urllib.quote(value)
    then = now + COOKIE_LIFETIME
    gmt = time.gmtime(then)
    path = os.environ.get('SCRIPT_NAME', '/cgi-bin/')
    print "Set-Cookie: %s=%s; path=%s;" % (name, value, path),
    print time.strftime("expires=%a, %d-%b-%y %X GMT", gmt)

class MagicDict:

    def __init__(self, d, quote):
        self.__d = d
        self.__quote = quote

    def __getitem__(self, key):
        for d in self.__d:
            try:
                value = d[key]
                if value:
                    value = str(value)
                    if self.__quote:
                        value = escapeq(value)
                    return value
            except KeyError:
                pass
        return ''

class UserInput:

    def __init__(self):
        self.__form = cgi.FieldStorage()
        #log("\n\nbody: " + self.body)

    def __getattr__(self, name):
        if name[0] == '_':
            raise AttributeError
        try:
            value = self.__form[name].value
        except (TypeError, KeyError):
            value = ''
        else:
            value = value.strip()
        setattr(self, name, value)
        return value

    def __getitem__(self, key):
        return getattr(self, key)

class FaqEntry:

    def __init__(self, fp, file, sec_num):
        self.file = file
        self.sec, self.num = sec_num
        if fp:
            import rfc822
            self.__headers = rfc822.Message(fp)
            self.body = fp.read().strip()
        else:
            self.__headers = {'title': "%d.%d. " % sec_num}
            self.body = ''

    def __getattr__(self, name):
        if name[0] == '_':
            raise AttributeError
        key = '-'.join(name.split('_'))
        try:
            value = self.__headers[key]
        except KeyError:
            value = ''
        setattr(self, name, value)
        return value

    def __getitem__(self, key):
        return getattr(self, key)

    def load_version(self):
        command = interpolate(SH_RLOG_H, self)
        p = os.popen(command)
        version = ''
        while 1:
            line = p.readline()
            if not line:
                break
            if line[:5] == 'head:':
                version = line[5:].strip()
        p.close()
        self.version = version

    def getmtime(self):
        if not self.last_changed_date:
            return 0
        try:
            return os.stat(self.file)[stat.ST_MTIME]
        except os.error:
            return 0

    def emit_marks(self):
        mtime = self.getmtime()
        if mtime >= now - DT_VERY_RECENT:
            emit(MARK_VERY_RECENT, self)
        elif mtime >= now - DT_RECENT:
            emit(MARK_RECENT, self)

    def show(self, edit=1):
        emit(ENTRY_HEADER1, self)
        self.emit_marks()
        emit(ENTRY_HEADER2, self)
        pre = 0
        raw = 0
        for line in self.body.split('\n'):
            # Allow the user to insert raw html into a FAQ answer
            # (Skip Montanaro, with changes by Guido)
            tag = line.rstrip().lower()
            if tag == '<html>':
                raw = 1
                continue
            if tag == '</html>':
                raw = 0
                continue
            if raw:
                print line
                continue
            if not line.strip():
                if pre:
                    print '</PRE>'
                    pre = 0
                else:
                    print '<P>'
            else:
                if not line[0].isspace():
                    if pre:
                        print '</PRE>'
                        pre = 0
                else:
                    if not pre:
                        print '<PRE>'
                        pre = 1
                if '/' in line or '@' in line:
                    line = translate(line, pre)
                elif '<' in line or '&' in line:
                    line = escape(line)
                if not pre and '*' in line:
                    line = emphasize(line)
                print line
        if pre:
            print '</PRE>'
            pre = 0
        if edit:
            print '<P>'
            emit(ENTRY_FOOTER, self)
            if self.last_changed_date:
                emit(ENTRY_LOGINFO, self)
        print '<P>'

class FaqDir:

    entryclass = FaqEntry

    __okprog = re.compile(OKFILENAME)

    def __init__(self, dir=os.curdir):
        self.__dir = dir
        self.__files = None

    def __fill(self):
        if self.__files is not None:
            return
        self.__files = files = []
        okprog = self.__okprog
        for file in os.listdir(self.__dir):
            if self.__okprog.match(file):
                files.append(file)
        files.sort()

    def good(self, file):
        return self.__okprog.match(file)

    def parse(self, file):
        m = self.good(file)
        if not m:
            return None
        sec, num = m.group(1, 2)
        return int(sec), int(num)

    def list(self):
        # XXX Caller shouldn't modify result
        self.__fill()
        return self.__files

    def open(self, file):
        sec_num = self.parse(file)
        if not sec_num:
            raise InvalidFile(file)
        try:
            fp = open(file)
        except IOError, msg:
            raise NoSuchFile(file, msg)
        try:
            return self.entryclass(fp, file, sec_num)
        finally:
            fp.close()

    def show(self, file, edit=1):
        self.open(file).show(edit=edit)

    def new(self, section):
        if not SECTION_TITLES.has_key(section):
            raise NoSuchSection(section)
        maxnum = 0
        for file in self.list():
            sec, num = self.parse(file)
            if sec == section:
                maxnum = max(maxnum, num)
        sec_num = (section, maxnum+1)
        file = NEWFILENAME % sec_num
        return self.entryclass(None, file, sec_num)

class FaqWizard:

    def __init__(self):
        self.ui = UserInput()
        self.dir = FaqDir()

    def go(self):
        print 'Content-type: text/html'
        req = self.ui.req or 'home'
        mname = 'do_%s' % req
        try:
            meth = getattr(self, mname)
        except AttributeError:
            self.error("Bad request type %s." % `req`)
        else:
            try:
                meth()
            except InvalidFile, exc:
                self.error("Invalid entry file name %s" % exc.file)
            except NoSuchFile, exc:
                self.error("No entry with file name %s" % exc.file)
            except NoSuchSection, exc:
                self.error("No section number %s" % exc.section)
        self.epilogue()

    def error(self, message, **kw):
        self.prologue(T_ERROR)
        emit(message, kw)

    def prologue(self, title, entry=None, **kw):
        emit(PROLOGUE, entry, kwdict=kw, title=escape(title))

    def epilogue(self):
        emit(EPILOGUE)

    def do_home(self):
        self.prologue(T_HOME)
        emit(HOME)

    def do_debug(self):
        self.prologue("FAQ Wizard Debugging")
        form = cgi.FieldStorage()
        cgi.print_form(form)
        cgi.print_environ(os.environ)
        cgi.print_directory()
        cgi.print_arguments()

    def do_search(self):
        query = self.ui.query
        if not query:
            self.error("Empty query string!")
            return
        if self.ui.querytype == 'simple':
            query = re.escape(query)
            queries = [query]
        elif self.ui.querytype in ('anykeywords', 'allkeywords'):
            words = filter(None, re.split('\W+', query))
            if not words:
                self.error("No keywords specified!")
                return
            words = map(lambda w: r'\b%s\b' % w, words)
            if self.ui.querytype[:3] == 'any':
                queries = ['|'.join(words)]
            else:
                # Each of the individual queries must match
                queries = words
        else:
            # Default to regular expression
            queries = [query]
        self.prologue(T_SEARCH)
        progs = []
        for query in queries:
            if self.ui.casefold == 'no':
                p = re.compile(query)
            else:
                p = re.compile(query, re.IGNORECASE)
            progs.append(p)
        hits = []
        for file in self.dir.list():
            try:
                entry = self.dir.open(file)
            except FileError:
                constants
            for p in progs:
                if not p.search(entry.title) and not p.search(entry.body):
                    break
            else:
                hits.append(file)
        if not hits:
            emit(NO_HITS, self.ui, count=0)
        elif len(hits) <= MAXHITS:
            if len(hits) == 1:
                emit(ONE_HIT, count=1)
            else:
                emit(FEW_HITS, count=len(hits))
            self.format_all(hits, headers=0)
        else:
            emit(MANY_HITS, count=len(hits))
            self.format_index(hits)

    def do_all(self):
        self.prologue(T_ALL)
        files = self.dir.list()
        self.last_changed(files)
        self.format_index(files, localrefs=1)
        self.format_all(files)

    def do_compat(self):
        files = self.dir.list()
        emit(COMPAT)
        self.last_changed(files)
        self.format_index(files, localrefs=1)
        self.format_all(files, edit=0)
        sys.exit(0)                     # XXX Hack to suppress epilogue

    def last_changed(self, files):
        latest = 0
        for file in files:
            entry = self.dir.open(file)
            if entry:
                mtime = mtime = entry.getmtime()
                if mtime > latest:
                    latest = mtime
        print time.strftime(LAST_CHANGED, time.localtime(latest))
        emit(EXPLAIN_MARKS)

    def format_all(self, files, edit=1, headers=1):
        sec = 0
        for file in files:
            try:
                entry = self.dir.open(file)
            except NoSuchFile:
                continue
            if headers and entry.sec != sec:
                sec = entry.sec
                try:
                    title = SECTION_TITLES[sec]
                except KeyError:
                    title = "Untitled"
                emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n",
                     sec=sec, title=title)
            entry.show(edit=edit)

    def do_index(self):
        self.prologue(T_INDEX)
        files = self.dir.list()
        self.last_changed(files)
        self.format_index(files, add=1)

    def format_index(self, files, add=0, localrefs=0):
        sec = 0
        for file in files:
            try:
                entry = self.dir.open(file)
            except NoSuchFile:
                continue
            if entry.sec != sec:
                if sec:
                    if add:
                        emit(INDEX_ADDSECTION, sec=sec)
                    emit(INDEX_ENDSECTION, sec=sec)
                sec = entry.sec
                try:
                    title = SECTION_TITLES[sec]
                except KeyError:
                    title = "Untitled"
                emit(INDEX_SECTION, sec=sec, title=title)
            if localrefs:
                emit(LOCAL_ENTRY, entry)
            else:
                emit(INDEX_ENTRY, entry)
            entry.emit_marks()
        if sec:
            if add:
                emit(INDEX_ADDSECTION, sec=sec)
            emit(INDEX_ENDSECTION, sec=sec)

    def do_recent(self):
        if not self.ui.days:
            days = 1
        else:
            days = float(self.ui.days)
        try:
            cutoff = now - days * 24 * 3600
        except OverflowError:
            cutoff = 0
        list = []
        for file in self.dir.list():
            entry = self.dir.open(file)
            if not entry:
                continue
            mtime = entry.getmtime()
            if mtime >= cutoff:
                list.append((mtime, file))
        list.sort()
        list.reverse()
        self.prologue(T_RECENT)
        if days <= 1:
            period = "%.2g hours" % (days*24)
        else:
            period = "%.6g days" % days
        if not list:
            emit(NO_RECENT, period=period)
        elif len(list) == 1:
            emit(ONE_RECENT, period=period)
        else:
            emit(SOME_RECENT, period=period, count=len(list))
        self.format_all(map(lambda (mtime, file): file, list), headers=0)
        emit(TAIL_RECENT)

    def do_roulette(self):
        import random
        files = self.dir.list()
        if not files: 
            self.error("No entries.")
            return
        file = random.choice(files)
        self.prologue(T_ROULETTE)
        emit(ROULETTE)
        self.dir.show(file)

    def do_help(self):
        self.prologue(T_HELP)
        emit(HELP)

    def do_show(self):
        entry = self.dir.open(self.ui.file)
        self.prologue(T_SHOW)
        entry.show()

    def do_add(self):
        self.prologue(T_ADD)
        emit(ADD_HEAD)
        sections = SECTION_TITLES.items()
        sections.sort()
        for section, title in sections:
            emit(ADD_SECTION, section=section, title=title)
        emit(ADD_TAIL)

    def do_delete(self):
        self.prologue(T_DELETE)
        emit(DELETE)

    def do_log(self):
        entry = self.dir.open(self.ui.file)
        self.prologue(T_LOG, entry)
        emit(LOG, entry)
        self.rlog(interpolate(SH_RLOG, entry), entry)

    def rlog(self, command, entry=None):
        output = os.popen(command).read()
        sys.stdout.write('<PRE>')
        athead = 0
        lines = output.split('\n')
        while lines and not lines[-1]:
            del lines[-1]
        if lines:
            line = lines[-1]
            if line[:1] == '=' and len(line) >= 40 and \
               line == line[0]*len(line):
                del lines[-1]
        headrev = None
        for line in lines:
            if entry and athead and line[:9] == 'revision ':
                rev = line[9:].split()
                mami = revparse(rev)
                if not mami:
                    print line
                else:
                    emit(REVISIONLINK, entry, rev=rev, line=line)
                    if mami[1] > 1:
                        prev = "%d.%d" % (mami[0], mami[1]-1)
                        emit(DIFFLINK, entry, prev=prev, rev=rev)
                    if headrev:
                        emit(DIFFLINK, entry, prev=rev, rev=headrev)
                    else:
                        headrev = rev
                    print
                athead = 0
            else:
                athead = 0
                if line[:1] == '-' and len(line) >= 20 and \
                   line == len(line) * line[0]:
                    athead = 1
                    sys.stdout.write('<HR>')
                else:
                    print line
        print '</PRE>'

    def do_revision(self):
        entry = self.dir.open(self.ui.file)
        rev = self.ui.rev
        mami = revparse(rev)
        if not mami:
            self.error("Invalid revision number: %s." % `rev`)
        self.prologue(T_REVISION, entry)
        self.shell(interpolate(SH_REVISION, entry, rev=rev))

    def do_diff(self):
        entry = self.dir.open(self.ui.file)
        prev = self.ui.prev
        rev = self.ui.rev
        mami = revparse(rev)
        if not mami:
            self.error("Invalid revision number: %s." % `rev`)
        if prev:
            if not revparse(prev):
                self.error("Invalid previous revision number: %s." % `prev`)
        else:
            prev = '%d.%d' % (mami[0], mami[1])
        self.prologue(T_DIFF, entry)
        self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev))

    def shell(self, command):
        output = os.popen(command).read()
        sys.stdout.write('<PRE>')
        print escape(output)
        print '</PRE>'

    def do_new(self):
        entry = self.dir.new(section=int(self.ui.section))
        entry.version = '*new*'
        self.prologue(T_EDIT)
        emit(EDITHEAD)
        emit(EDITFORM1, entry, editversion=entry.version)
        emit(EDITFORM2, entry, load_my_cookie())
        emit(EDITFORM3)
        entry.show(edit=0)

    def do_edit(self):
        entry = self.dir.open(self.ui.file)
        entry.load_version()
        self.prologue(T_EDIT)
        emit(EDITHEAD)
        emit(EDITFORM1, entry, editversion=entry.version)
        emit(EDITFORM2, entry, load_my_cookie())
        emit(EDITFORM3)
        entry.show(edit=0)

    def do_review(self):
        send_my_cookie(self.ui)
        if self.ui.editversion == '*new*':
            sec, num = self.dir.parse(self.ui.file)
            entry = self.dir.new(section=sec)
            entry.version = "*new*"
            if entry.file != self.ui.file:
                self.error("Commit version conflict!")
                emit(NEWCONFLICT, self.ui, sec=sec, num=num)
                return
        else:
            entry = self.dir.open(self.ui.file)
            entry.load_version()
        # Check that the FAQ entry number didn't change
        if self.ui.title.split()[:1] != entry.title.split()[:1]:
            self.error("Don't change the entry number please!")
            return
        # Check that the edited version is the current version
        if entry.version != self.ui.editversion:
            self.error("Commit version conflict!")
            emit(VERSIONCONFLICT, entry, self.ui)
            return
        commit_ok = ((not PASSWORD
                      or self.ui.password == PASSWORD) 
                     and self.ui.author
                     and '@' in self.ui.email
                     and self.ui.log)
        if self.ui.commit:
            if not commit_ok:
                self.cantcommit()
            else:
                self.commit(entry)
            return
        self.prologue(T_REVIEW)
        emit(REVIEWHEAD)
        entry.body = self.ui.body
        entry.title = self.ui.title
        entry.show(edit=0)
        emit(EDITFORM1, self.ui, entry)
        if commit_ok:
            emit(COMMIT)
        else:
            emit(NOCOMMIT_HEAD)
            self.errordetail()
            emit(NOCOMMIT_TAIL)
        emit(EDITFORM2, self.ui, entry, load_my_cookie())
        emit(EDITFORM3)

    def cantcommit(self):
        self.prologue(T_CANTCOMMIT)
        print CANTCOMMIT_HEAD
        self.errordetail()
        print CANTCOMMIT_TAIL

    def errordetail(self):
        if PASSWORD and self.ui.password != PASSWORD:
            emit(NEED_PASSWD)
        if not self.ui.log:
            emit(NEED_LOG)
        if not self.ui.author:
            emit(NEED_AUTHOR)
        if not self.ui.email:
            emit(NEED_EMAIL)

    def commit(self, entry):
        file = entry.file
        # Normalize line endings in body
        if '\r' in self.ui.body:
            self.ui.body = re.sub('\r\n?', '\n', self.ui.body)
        # Normalize whitespace in title
        self.ui.title = ' '.join(self.ui.title.split())
        # Check that there were any changes
        if self.ui.body == entry.body and self.ui.title == entry.title:
            self.error("You didn't make any changes!")
            return

        # need to lock here because otherwise the file exists and is not writable (on NT)
        command = interpolate(SH_LOCK, file=file)
        p = os.popen(command)
        output = p.read()

        try:
            os.unlink(file)
        except os.error:
            pass
        try:
            f = open(file, 'w')
        except IOError, why:
            self.error(CANTWRITE, file=file, why=why)
            return
        date = time.ctime(now)
        emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0)
        f.write('\n')
        f.write(self.ui.body)
        f.write('\n')
        f.close()

        import tempfile
        tf = tempfile.NamedTemporaryFile()
        emit(LOGHEADER, self.ui, os.environ, date=date, _file=tfn)
        tf.flush()
        tf.seek(0)

        command = interpolate(SH_CHECKIN, file=file, tfn=tf.name)
        log("\n\n" + command)
        p = os.popen(command)
        output = p.read()
        sts = p.close()
        log("output: " + output)
        log("done: " + str(sts))
        log("TempFile:\n" + tf.read() + "end")
        
        if not sts:
            self.prologue(T_COMMITTED)
            emit(COMMITTED)
        else:
            self.error(T_COMMITFAILED)
            emit(COMMITFAILED, sts=sts)
        print '<PRE>%s</PRE>' % escape(output)

        try:
            os.unlink(tfn)
        except os.error:
            pass

        entry = self.dir.open(file)
        entry.show()

wiz = FaqWizard()
wiz.go()
