# -*- coding: utf-8 -*-
"""
MoinMoin - Dump a MoinMoin wiki to static pages
Version modifiée par ADG pour les besoins du Cr@ns.
Ce fichier devrait être linké dans /usr/lib/python2.7/dist-packages/MoinMoin/script/export

@copyright: 2002-2004 Juergen Hermann <jh@web.de>,
            2005-2006 MoinMoin:ThomasWaldmann
@license: GNU GPL, see COPYING for details.
"""

import sys, os, time, codecs, shutil, re, errno

from MoinMoin import config, wikiutil, Page, user
from MoinMoin import script
from MoinMoin.action import AttachFile

url_prefix_static = "."
logo_html = '<img src="logo.png">'
HTML_SUFFIX = ".html"

page_template = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=%(charset)s">
  <title>%(pagename)s</title>
  <style type="text/css">
/*  common.css - MoinMoin Default Styles
Copyright (c) 2001, 2002, 2003 by Juergen Hermann
*/

/* content styles */
html { background-color: white; color: black; font-family: sans-serif; font-size: 0.85em; line-height: 1.1em; }
body { margin: 0; }

/* Links */
a {color: #0044B3;}
a:visited {color: #597BB3;}
a.nonexistent, a.badinterwiki {color: gray;}

/* Headings */
h1 { margin: 0; padding: 0; color: black; font-size: 2em; font-weight: bold; line-height: 1.2em; /*display: none;*/ }
h1 a, h1 a:visited { text-decoration: none; color: black; /*display: none;*/ }
h2, h3, h4, h5, h6 { margin: 0.9em 0 0 0; padding: 0; color: black; line-height: 1.2em; }
h2 { font-size: 2em; width:100%%; border-bottom: thin solid red; /*background: url(../img/BarreRouge.png) repeat-x;*/ text-align:left; }
h3 {font-size: 1.3em;}
h4 {font-size: 1.1em;}
h5, h6 {font-size: 1em;}
tt {font-size: 1em;}
li p { margin: .25em 0; }
li.gap { margin-top: 0.5em;}
dt { margin-top: 0.5em; font-weight: bold; }
dd { margin-top: 0; margin-bottom: 0; }
dd p { margin: 0.25em 0;}
a, img, img.drawing { border: 0; }
pre { border: 1pt solid #AEBDCC; background-image: url(../img/bleutransparent.png); padding: 5pt; font-family: courier, monospace; white-space: pre;
/* begin css 3 or browser specific rules - do not remove!
	see: http://forums.techguy.org/archive/index.php/t-249849.html */
 white-space: pre-wrap; word-wrap: break-word; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; /* end css 3 or browser specific rules */ }
table { margin: 0.5em 0; border-collapse: collapse; }
td { padding: 0.25em; border: 1pt solid #ADB9CC; }
td p { margin: 0; padding: 0; }
.footnotes div { width: 5em; border-top: 1pt solid gray; }
.footnotes ul { padding: 0 2em; margin: 0 0 1em; list-style: none; }
.footnotes li { }
.info { font-size: 0.85em; color: gray; }
#pageinfo { margin-top: 2em; }
.seperator { color: gray; }

/* standard rule ---- */
hr { clear: both; height: 1pt; background-color: #9C9C9C; border: 0;}

/* custom rules ----- to ---------- */
.hr1 {height: 2pt;}
.hr2 {height: 3pt;}
.hr3 {height: 4pt;}
.hr4 {height: 5pt;}
.hr5 {height: 6pt;}
.hr6 {height: 7pt;}

/* Replacement for html 3 u tag */
.u {text-decoration: underline;}

/* eye catchers */
.warning { color: red; }
.error { color: red; }
strong.highlight { background-color: #CCE0FF; padding: 1pt; }

/* Recent changes */
.rcrss { float: right;margin: 0;}
.recentchanges[dir="rtl"] .rcrss {float: left;}
.recentchanges table {clear: both;}
.recentchanges td {vertical-align: top; border: none; border-bottom: 1pt solid #E6EAF0; background: #F2F4F7;}
.rcdaybreak td { background: #B8C5D9;border: none;}
.rcdaybreak td a {font-size: 0.88em;}
.rcicon1, .rcicon2 {text-align: center;}
.rcpagelink {width: 33%%;}
.rctime {font-size: 0.88em;white-space: nowrap;}
.rceditor {white-space: nowrap;	font-size: 0.88em;}
.rccomment {width: 66%%; color: gray;font-size: 0.88em;}

/* User Preferences */
.userpref table, .userpref td {	border: none;}

/* CSS for new code_area markup used by Colorizer and ParserBase */
div.codearea { /* the div makes the border */margin: 0.5em 0;padding: 0;border: 1pt solid #AEBDCC;background-color: #F3F5F7;color: black;}
div.codearea pre { /* the pre has no border and is inside the div */
	margin: 0;padding: 10pt;border: none;}
a.codenumbers { /* format of the line numbering link */
	margin: 0 10pt; font-size: 0.85em; color: gray;}

/* format of certain syntax spans */
div.codearea pre span.LineNumber {color: gray;}
div.codearea pre span.ID         {color: #000000;}
div.codearea pre span.Operator   {color: #0000C0;}
div.codearea pre span.Char       {color: #004080;}
div.codearea pre span.Comment    {color: #008000;}
div.codearea pre span.Number     {color: #0080C0;}
div.codearea pre span.String     {color: #004080;}
div.codearea pre span.SPChar     {color: #0000C0;}
div.codearea pre span.ResWord    {color: #A00000;}
div.codearea pre span.ConsWord   {color: #008080; font-weight: bold;}
div.codearea pre span.Error      {color: #FF8080; border: solid 1.5pt #FF0000;}
div.codearea pre span.ResWord2   {color: #0080ff; font-weight: bold;}
div.codearea pre span.Special    {color: #0000ff;}
div.codearea pre span.Preprc     {color: #803999;}


/* Search results */
.searchresults dt { margin-top: 1em; font-weight: normal;}
.searchresults dd { font-size: 0.85em;}

/* Liens dactions */
.editbar { display: block;}
.editbar li { float: left; padding: 0;}

#wrapper { width: 50em; margin:0 auto; padding:1em 2em 1em 5em; text-align: left;}
#wrapper img#logo { margin-left: -4em; margin-bottom: 2em;}

/*<!-- DATE DE MISE A JOUR -->*/
p.creation { margin-top: 5em;border-top: 1px solid #6C7680;font-style: italic;color: gray; padding: 10px 30px ;}
  </style>
 </head>
 <body>
<div id="wrapper">
<img id="logo" src="data:image/png;base64,
[encoded data, 47124 characters]
YII=" />
<div dir="ltr" id="content" lang="fr">
%(pagehtml)s
</div>

<p class="creation">
Cette page a été extraite du wiki le %(timestamp)s.
</p>
</div>
</body>
</html>
'''


def _attachment(request, pagename, filename, outputdir, **kw):
    filename = filename.encode(config.charset)
    source_dir = AttachFile.getAttachDir(request, pagename)
    source_file = os.path.join(source_dir, filename)
    dest_dir = os.path.join(outputdir, "attachments", wikiutil.quoteWikinameFS(pagename))
    dest_file = os.path.join(dest_dir, filename)
    dest_url = "attachments/%s/%s" % (wikiutil.quoteWikinameFS(pagename), wikiutil.url_quote(filename))
    if os.access(source_file, os.R_OK):
        if not os.access(dest_dir, os.F_OK):
            try:
                os.makedirs(dest_dir)
            except:
                script.fatal("Cannot create attachment directory '%s'" % dest_dir)
        elif not os.path.isdir(dest_dir):
            script.fatal("'%s' is not a directory" % dest_dir)

        shutil.copyfile(source_file, dest_file)
        script.log('Writing "%s"...' % dest_url)
        return dest_url
    else:
        return ""


class PluginScript(script.MoinScript):
    """\
Purpose:
========
This tool allows you to dump MoinMoin wiki pages to static HTML files.

Detailed Instructions:
======================
General syntax: moin [options] export dump_proxy [dump-options]

[options] usually should be:
    --config-dir=/path/to/my/cfg/ --wiki-url=http://wiki.example.org/

[dump-options] see below:
    0. You must run this script as owner of the wiki files, usually this is the
       web server user.

    1. To dump all the pages on the wiki to the directory '/mywiki'
       moin ... export dump_proxy --target-dir=/mywiki

    2. To dump all the pages readable by 'JohnSmith' on the wiki to the directory
       '/mywiki'
       moin ... export dump_proxy --target-dir=/mywiki --username JohnSmith
"""

    def __init__(self, argv=None, def_values=None):
        script.MoinScript.__init__(self, argv, def_values)
        self.parser.add_option(
            "-t", "--target-dir", dest = "target_dir",
            help = "Write html dump to DIRECTORY"
        )
        self.parser.add_option(
            "-u", "--username", dest = "dump_user",
            help = "User the dump will be performed as (for ACL checks, etc)"
        )

    def mainloop(self):
        """ moin-dump's main code. """

        # Prepare output directory
        if not self.options.target_dir:
            script.fatal("you must use --target-dir=/your/output/path to specify the directory we write the html files to")
        outputdir = os.path.abspath(self.options.target_dir)
        try:
            os.mkdir(outputdir)
            script.log("Created output directory '%s'!" % outputdir)
        except OSError, err:
            if err.errno != errno.EEXIST:
                script.fatal("Cannot create output directory '%s'!" % outputdir)

        # Insert config dir or the current directory to the start of the path.
        config_dir = self.options.config_dir
        if config_dir and os.path.isfile(config_dir):
            config_dir = os.path.dirname(config_dir)
        if config_dir and not os.path.isdir(config_dir):
            script.fatal("bad path given to --config-dir option")
        sys.path.insert(0, os.path.abspath(config_dir or os.curdir))

        self.init_request()
        request = self.request

        # fix url_prefix_static so we get relative paths in output html
        request.cfg.url_prefix_static = url_prefix_static

        # use this user for permissions checks
        request.user = user.User(request, name=self.options.dump_user)

        pages = request.rootpage.getPageList(user='') # get list of all pages in wiki
        pages.sort()
        if self.options.page: # did user request a particular page or group of pages?
            try:
                namematch = re.compile(self.options.page)
                pages = [page for page in pages if namematch.match(page)]
                if not pages:
                    pages = [self.options.page]
            except:
                pages = [self.options.page]

        wikiutil.quoteWikinameURL = lambda pagename, qfn=wikiutil.quoteWikinameFS: (qfn(pagename) + HTML_SUFFIX)

        AttachFile.getAttachUrl = lambda pagename, filename, request, **kw: _attachment(request, pagename, filename, outputdir, **kw)

        errfile = os.path.join(outputdir, 'error.log')
        errlog = open(errfile, 'w')
        errcnt = 0

        page_front_page = wikiutil.getLocalizedPage(request, request.cfg.page_front_page).page_name
        page_title_index = wikiutil.getLocalizedPage(request, 'TitleIndex').page_name
        page_word_index = wikiutil.getLocalizedPage(request, 'WordIndex').page_name

        navibar_html = ''
        for p in [page_front_page, page_title_index, page_word_index]:
            navibar_html += '[<a href="%s">%s</a>]&nbsp;' % (wikiutil.quoteWikinameURL(p), wikiutil.escape(p))

        urlbase = request.url # save wiki base url
        for pagename in pages:
            # we have the same name in URL and FS
            file = wikiutil.quoteWikinameURL(pagename)
            script.log('Writing "%s"...' % file)
            try:
                pagehtml = ''
                request.url = urlbase + pagename # add current pagename to url base
                page = Page.Page(request, pagename)
                request.page = page
                try:
                    request.reset()
                    pagehtml = request.redirectedOutput(page.send_page, count_hit=0, content_only=1)
                except:
                    errcnt = errcnt + 1
                    print >> sys.stderr, "*** Caught exception while writing page!"
                    print >> errlog, "~" * 78
                    print >> errlog, file # page filename
                    import traceback
                    traceback.print_exc(None, errlog)
            finally:
                timestamp = time.strftime("%Y-%m-%d %H:%M")
                filepath = os.path.join(outputdir, file)
                fileout = codecs.open(filepath, 'w', config.charset)
                fileout.write(page_template % {
                    'charset': config.charset,
                    'pagename': pagename,
                    'pagehtml': pagehtml,
                    'timestamp': timestamp,
                })
                fileout.close()

        # copy FrontPage to "index.html"
        indexpage = page_front_page
        if self.options.page:
            indexpage = pages[0] # index page has limited use when dumping specific pages, but create one anyway
        shutil.copyfile(
            os.path.join(outputdir, wikiutil.quoteWikinameFS(indexpage) + HTML_SUFFIX),
            os.path.join(outputdir, 'index' + HTML_SUFFIX)
        )

        errlog.close()
        if errcnt:
            print >> sys.stderr, "*** %d error(s) occurred, see '%s'!" % (errcnt, errfile)

