#!/usr/bin/python -OO

"""
sbin/web2ldap.py - startscript for running as stand-alone HTTP server

web2ldap -  web-based LDAP Client, see http://www.web2ldap.de
(c) by Michael Stroeder <michael@stroeder.com>

This software is distributed under the terms of the
GPL (GNU GENERAL PUBLIC LICENSE) Version 2
(see http://www.gnu.org/copyleft/gpl.html)
"""

import sys,os,signal

try:
  from netaddr import IPNetwork
except ImportError:
  from ipaddr import IPNetwork

exec_startdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
sys.path.insert(0,os.path.join(exec_startdir,'pylib'))
sys.path.insert(0,os.path.join(exec_startdir,'etc','web2ldap'))

if os.name == 'posix':
  # For finding web2ldapcnf.py in /etc/web2ldap on Unix systems
  sys.path.append('/etc/web2ldap')

# Import configuration modules
import web2ldapcnf.misc,web2ldapcnf.standalone

# Extend sys.path with modules dirs from configuration
for i in web2ldapcnf.misc.pylibdirs:
  sys.path.insert(0,i)

# Strictly these imports have to be done after extending sys.path
import web2ldapcnf.plugins
import mssignals,w2lapp.handler,msHTTPServer,msHTTPHandler


class web2ldapHTTPHandlerClass(msHTTPHandler.HTTPHandlerClass):
  script_name = '/web2ldap'
  base_url = None
  server_env = {
    'SERVER_SOFTWARE':'web2ldap %s' % w2lapp.__version__,
    'SERVER_ADMIN':web2ldapcnf.standalone.server_admin,
    'DOCUMENT_ROOT':web2ldapcnf.standalone.document_root,
    'SERVER_SIGNATURE':web2ldapcnf.standalone.server_signature,
  }
  dir_listing_allowed = web2ldapcnf.standalone.dir_listing_allowed
  reverse_lookups = web2ldapcnf.standalone.reverse_lookups
  access_allowed   = map(IPNetwork,web2ldapcnf.standalone.access_allowed)
  extensions_map = msHTTPHandler.getExtensionMap(web2ldapcnf.standalone.mime_types)

  # Start web2ldap itself.
  def run_app(self,http_env):
    msHTTPHandler.HTTPHandlerClass.run_app(self,http_env)
    # Call web2ldap application handler function
    w2lapp.handler.HandleHTTPRequest(
      self.rfile,self.wfile,self.error_log,http_env,self.base_url
    )
    return

server_address,run_detached,run_threaded,ssl_enabled,uid = \
  msHTTPServer.GetCommandlineParams(
    msHTTPServer.split_server_address(
      web2ldapcnf.standalone.bind_address,('127.0.0.1',1760)
    ),
    os.name == 'posix',
    1,
    0,
    web2ldapcnf.standalone.run_username
  )

# Set active signal handler for stand-alone mode
signal.signal(signal.SIGTERM,mssignals.TERMSignalHandler)

if run_detached:
  # Detach from console means logging to files.
  # Log files are opened before dropping privileges to avoid having to
  # grant write permission to log file directory to non-privileged user
  web2ldapHTTPHandlerClass.access_log = open(web2ldapcnf.standalone.access_log,'a',1)
  web2ldapHTTPHandlerClass.error_log = open(web2ldapcnf.standalone.error_log,'a',1)
  web2ldapHTTPHandlerClass.debug_log = open(web2ldapcnf.standalone.debug_log,'a',1)
  pid_file = open(web2ldapcnf.standalone.pid_file,'w')

# Change UID if one was defined
if (not uid is None) and (uid!=os.getuid()):
  try:
    os.setuid(uid)
    print 'Changed to UID %d.' % (uid)
  except os.error:
    print 'Error changing to UID %d! Aborting.' % (uid)
    sys.exit(1)

# Force use of a pseudo-random salt to make hash() values before forking
os.environ['PYTHONHASHSEED'] = 'random'

if run_detached:
  if os.fork():
    sys.exit(0)
  else:
    os.setsid()
    # Write PID to file. Has to be done after forking!
    pid_file.write(str(os.getpid()))
    pid_file.close()
    sys.stdin.close()
    sys.stdout.close()
    sys.stdout = web2ldapHTTPHandlerClass.debug_log
    sys.stderr.close()
    sys.stderr = web2ldapHTTPHandlerClass.error_log
else:
  # Log to console
  web2ldapHTTPHandlerClass.access_log = sys.stdout
  web2ldapHTTPHandlerClass.error_log = sys.stderr
  web2ldapHTTPHandlerClass.debug_log = sys.stdout

web2ldapHTTPHandlerClass.base_url = web2ldapcnf.standalone.base_url

# Start the clean-up thread
import w2lapp.session
w2lapp.session.cleanUpThread.start()

try:
  msHTTPServer.RunServer(
    web2ldapHTTPHandlerClass,
    server_address,
    run_detached,
    run_threaded,
    0
  )
except KeyboardInterrupt,SystemExit:
  # Stop clean-up thread
  w2lapp.session.cleanUpThread.enabled=0
  if run_detached:
    # Remove the PID file
    web2ldapHTTPHandlerClass.debug_log.write(
      'Trying to remove PID file %s\n' % (web2ldapcnf.standalone.pid_file)
    )
    os.remove(web2ldapcnf.standalone.pid_file)
