# -*- coding: UTF-8 -*-
###########################################################################
# Eole NG - 2007
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
# Licence CeCill  cf /root/LicenceEole.txt
# eole@ac-dijon.fr
#
# zprtap.py
#
# création et démarrage des services zephir_web
#
###########################################################################

# filtrage des warnings à l'importation de nevow
import warnings
try:
    from twisted.python.components import ComponentsDeprecationWarning
    warnings.filterwarnings('ignore', category=ComponentsDeprecationWarning, message="Please don't use __adapt__ on Interface subclasses")
except:
    # twisted 1 : pas besoin de filtrer ce warning
    pass

from twisted.application import internet
from twisted.web import server, static
from zephir.certificats import ServerContextFactory

from zephir.web.config import CSS_DIR
from zephir.web.config import FONTS_DIR
from zephir.web.config import IMAGE_DIR
from zephir.web.config import PORT_WEB
from zephir.web.config import PATH_TEMP
from zephir.web.config import HELP_DIR
from zephir.web.config import SESSION_TIMEOUT
from zephir.web.config import ROOT_DIR
from zephir.web.config import selected_theme
from zephir.web.config import NOBODY_GID
from zephir.web.config import NOBODY_UID
from zephir.web.html import index
from zephir.web.template.page import FileEole
# import de eolegenconfig
from zephir.web.genconfig import GenConfig
#from zephir.web.genconfig1 import GenConfig as GenConfig1


# options ligne de commande
from twisted.python import usage, log, syslog

import os, shutil

class Options(usage.Options):
    optParameters = [["port", "p", PORT_WEB,
                      "Numero de port pour le serveur web."]]


##### Gestion du thème au démarrage du service #####

# si le thème a changé, on met à jour les fichiers (images)
try:
    current_theme = open(ROOT_DIR + 'web/current_theme').read().strip()
    assert os.path.isdir("%s/web/themes/%s" % (ROOT_DIR, current_theme))
except:
    # thème courant invalide ou jamais déployé
    current_theme = ""
if not os.path.isdir("%s/web/themes/%s" % (ROOT_DIR, selected_theme)):
    # thème sélectionné invalide, on utilise le thème classique
    selected_theme == "genConfig"
# mise à jour des fichiers si nécessaire
if current_theme != selected_theme:
    os.system('%s/utils/update_theme.sh %s' % (ROOT_DIR, selected_theme))
else:
    data_dir = {"images":IMAGE_DIR, "fonts":FONTS_DIR, "css":CSS_DIR}
    for source, destination in data_dir.items():
        if not os.path.isdir(destination):
            os.makedirs(destination)
        # si thème déjà en place, on vérifie si de nouvelles images ont été ajoutées au thème d'origine
        orig_imgdir = os.path.join(ROOT_DIR, "web", "themes", selected_theme, source)
        for img_file in os.listdir(orig_imgdir):
            if not os.path.exists(os.path.join(destination, img_file)):
                # image/répertoire non installés
                if os.path.isdir(os.path.join(orig_imgdir, img_file)):
                    shutil.copytree(os.path.join(orig_imgdir, img_file), os.path.join(destination, img_file))
                else:
                    shutil.copy(os.path.join(orig_imgdir, img_file), os.path.join(destination, img_file))

class ZephirWebSession(server.Session):
    """session web avec timeout configurable
    """
    sessionTimeout = SESSION_TIMEOUT

class ZephirSite(server.Site):
    sessionFactory = ZephirWebSession

    def _drop_privileges(self):
        #drop de privileges vers nobody/nobody
        #print "dropping privileges (%s)" % self.__module__.split('.')[-1]
        os.setegid(NOBODY_GID)
        os.seteuid(NOBODY_UID)

    def _gain_privileges(self):
        #on reprend nos privileges initiaux
        #print "gaining privileges (%s)" % self.__module__.split('.')[-1]
        os.seteuid(self.UID)
        os.setegid(self.GID)

    def startFactory(self):
        #sauvegarde de notre UIG/GID courant
        self.UID = os.getuid()
        self.GID = os.getgid()
        # mise à jour du préfixe de log (twisted par défaut)
        # FIX : on conserve la référence à l'ancien observer pour
        # éviter les pb à la fermeture du service
        self.old_obs = None
        if len(log.theLogPublisher.observers) >= 1:
            self.old_obs = log.theLogPublisher.observers[0]
        new_obs = syslog.SyslogObserver('zephir_web', options=syslog.DEFAULT_OPTIONS, facility=syslog.DEFAULT_FACILITY)
        log.addObserver(new_obs.emit)
        log.removeObserver(self.old_obs)
        # passage en utilisateur 'nobody'
        self._drop_privileges()
        # création du répertoire temporaire si besoin (supprimé en cas de reboot)
        if not os.path.isdir(PATH_TEMP):
            os.makedirs(PATH_TEMP)
        server.Site.startFactory(self)

    def stopFactory(self):
        # on reprend les privilèges pour pouvoir supprimer le fichier de PID
        self._gain_privileges()
        if self.old_obs:
            log.removeObserver(log.theLogPublisher.observers[0])
            log.addObserver(self.old_obs)
        server.Site.stopFactory(self)

def makeService(config):
    # port TCP à écouter
    port = int(config["port"])

    root = index.Index()
    root.putChild(b"images", static.File(IMAGE_DIR))
    root.putChild(b"aide", static.File(HELP_DIR))
    root.putChild(b"tmp", FileEole(PATH_TEMP))
    root.putChild(b"css", static.File(CSS_DIR))
    root.putChild(b"fonts", static.File(FONTS_DIR))
    # service des pages statiques de genconfig si disponibles
    root.putChild(b"genconfig", GenConfig())
#    root.putChild(b"genconfig1", GenConfig1())
    site = ZephirSite(root)
    site.timeOut = 600

    return internet.SSLServer(port, site, ServerContextFactory())
